1

I am trying to build a function grapher,

The user enters xmin, xmax, ymin, ymax, function. I got the x, y for all points.

Now i want to translate this initial referential to a Canvas starting at 0,0 up to 250,250.

Is there a short way or should i just check

if x < 0 
new x = (x - xmin) * (250 / (xmax - xmin)) ?

etc ..

Also this basic approach does not optimise sampling. For example if my function f(x) = 5 i dont need to sample the xrange in 500 points, i only need two points. I could do some heuristic checks.

But for a function like sin(2/x) i need more sampling around x (-1,1) how would you aproach such a thing ?

Thanks

coulix
  • 3,328
  • 6
  • 55
  • 81

3 Answers3

1

Instead of iterating over x in the original coordinates, iterate over the canvas and then transform back to the original coordinates:

for (int xcanvas = 0; xcanvas <= 250; i++) {
    double x = ((xmax - xmin) * xcanvas / 250.0) + xmin;
    double y = f(x);

    int ycanvas = 250 * (y - ymin) / (ymax - ymin) + .5;

    // Plot (xcanvas, ycanvas)
}

This gives you exactly one function evaluation for each column of the canvas.

David Norman
  • 19,396
  • 12
  • 64
  • 54
  • What about the sampling part? – Shashwat Jul 17 '12 at 06:29
  • This does exactly one sample per pixel, which ought to be enough for most functions. You could dynamically check adjacent pixels in adjacent columns of the canvas to see if they are far apart and add in more samples if you wanted. – David Norman Jul 17 '12 at 14:56
0
  1. You can estimate the derivative (if you have one).
  2. You can use bidirectional (dichotomic) approach: estimate the difference and split the segment if necessary.
avp
  • 4,895
  • 4
  • 28
  • 40
0

I think I would start by reasoning about this in terms of transformations from canvas to maths contexts.

(canvas_x, canvas_y) -> (maths_x, maths_y)
(maths_x, maths_y)   -> (canvas_x, canvas_y)

maths_x -> maths_y

You iterate over the points that a displayable, looping over canvas_x.

This would translate to some simple functions:

maths_x = maths_x_from_canvas_x(canvas_x, min_maths_x, max_maths_x)
maths_y = maths_y_from_maths_x(maths_x) # this is the function to be plotted.
canvas_y = canvas_y_from_maths_y(maths_y, min_maths_y, max_maths_y)

if (canvas_y not out of bounds) plot(canvas_x, canvas_y)

Once you get here, it's relatively simple to write these simple functions into code.

Optimize from here.

I think that for this approach, you won't need to know too much about sample frequencies, because you sample at a rate appropriate for the display. It wouldn't be optimal - your example of y = 5 is a good example, but you'd be guaranteed not to sample more than you can display.

jamesh
  • 19,863
  • 14
  • 56
  • 96