[racket] Plot: #:samples parameter of function---is this what was meant?

From: Deren Dohoda (deren.dohoda at gmail.com)
Date: Fri Apr 27 17:31:53 EDT 2012

Thanks, Neil. I don't mind. Clearly rough sampling would make plots
really icky. That's not at all my goal. It was more like localization
of the parameters.--- which is still true under the current
interpretation, just not in a way I expected.

Backstory: I was plotting splines and it was extremely slow and at
first all I found to speed things up was to decrease the number of
samples... with predictable results. What I had done was interpolate
520 points, generating 519 polynomials evaluated over a short
distance, which when plotted used (function ... ) 519 times. I was
getting worried that it was trying to plot all 519 functions over the
entire range but then discarding results not wanted to be seen or
something, which got me worried that I couldn't plot these at all
because my range was really large and to see the results I needed
quite a few samples. But in the end the problem wasn't sampling in the
way this mentioned: after I packed all 519 cubics into a single
procedure which knew on its own which part of the spline to evaluate
for a given x-value, necessitating a single (function ...) in the
renderer tree, everything went as fast as I'd originally hoped.

Which means, short version: plot is still awesome.


On Fri, Apr 27, 2012 at 4:30 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
> Sorry it took so long to reply. I let my email backlog get too large.
> On 04/18/2012 01:27 PM, Deren Dohoda wrote:
>> This is very counter-intuitive to me:
>> #lang racket
>> (require plot)
>> (plot (list (axes)
>>             (function (λ(x) (* x x)) #:samples 4 -2 0) ; 2 samples?!
>>             (function (λ(x) (* x x)) #:samples 8 0 2))) ; 4 samples?!
>> It is really surprising to suppose that the number of samples isn't
>> specifying the number of times to sample this function *in the range
>> given*. Was this intentional?
> It's because of how I abstracted sampling for renderers that graph one-,
> two- and three-input functions. Try this 3D plot:
> #lang racket
> (require plot)
> (plot3d (list (contour-intervals3d (λ (x y) (* x (+ (abs x) (abs y))))
>                                   -1.05 0 -2 2)
>              (contour-intervals3d (λ (x y) (* x (+ (sqr x) (sqr y))))
>                                   0 2.95 -2 2)))
> If each renderer returned by `contour-intervals3d' sampled 41 points in its
> x-axis bounds, the left half of the plot would be made of tiny rectangles,
> and the right half would be made of large ones. Ugliness!
> Another reason is that polygons are a lot easier to sort by depth if they're
> on a grid. To ensure the polygons are put on a grid, both renderers sample
> their functions at the same points even though they have different bounds.
> (If you were wondering, 3D polygons have to be sorted by depth and drawn
> back-to-front. Racket's device contexts don't have depth buffers, and
> neither do PDFs.)
> The renderers returned by `function' use the same sampling code as those
> returned by `contour-intervals3d'. So... there's a good reason.
> I honestly didn't think anybody would mind. Noticeable discretization in a
> 2D graph is generally a bad thing. But if you want it noticeable, you'd have
> more control using `lines':
> #lang racket
> (require plot plot/utils)
> (define (x-sqr-x x) (vector x (sqr x)))
> (plot (list (lines (map x-sqr-x (linear-seq -2 0 4)))
>            (lines (map x-sqr-x (linear-seq 0 2 8)))))
> But that's like... like plotting things in R. Icky. :P
> Neil ⊥
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users

Posted on the users mailing list.