Algorithm to zoom a plotted function

| | August 11, 2015

I’m making a game in android and I need plot a function, my algorithm is this:

    @Override
    protected void onDraw(Canvas canvas) {
        float e = 0.5f; 
        //from -x axis to +x evaluate f(x) 
        for (float x = -z(canvas.getWidth()); x < z(canvas.getWidth()); x+=e) {
                 float x1,y1;
                 x1 = x;
                 y1 = f(x);
                 canvas.drawPoint((canvas.getWidth()/2)+x1, (canvas.getHeight()/2)-y1, paintWhite);
        }   
        super.onDraw(canvas);
    }

This is how it works. If my function is, for example f(x)=x^2, then z(x) is sqrt(x). I evaluate each point between -z(x) to z(x) and then I draw them. As you can see I use the half of the size of the screen to put the function in the middle of the screen. The problem isn’t that the code isn’t working, actually plots the function. But if the screen is of 320*480 then this function will be really tiny like in the image below. My question is: how can I change this algorithm to scale the function?. BTW what I’m really wanting to do is trace a route to later display an animated sprite, so actually scale this image doesnt gonna help me. I need change the algorithm in order to draw the same interval but in a larger space. Any tip helps, thanks!

Current working result

enter image description here

Desired result

enter image description here

UPDATE:
I will try explain more in detail what the problem is. Given this interval [-15…15] (-z(x) to z(x)) I need divide this points in a bigger interval [-320…320] (-x to x). For example, when you use some plotting software like this one. Although the div where is contain the function has 640 px of width, you dont see that the interval is from -320 to 320, you see that the interval is from -6 to 6. How can I achieve this?

3 Responses to “Algorithm to zoom a plotted function”

  1. Márcio Martins on November 30, -0001 @ 12:00 AM

    Like Anastasios mentioned, you would be better off creating a “virtual coordinate space” for yourself, compute everything in this virtual space, and then when drawing, convert to pixel coordinates.

    Basically, for the horizontal axis, you could create a function that converts from virtual coordinates <=> pixel coordinates. In c++ pseudo-code it would be something like this:

    int virtualToScreenX(float vx) {
      return floorf(((vx - virtualMinX) / (virtualMaxX - virtualMinX)) * physicalWidth);
    }
    
    float screenToVirtualX(int sx) {
      return virtualMinX + (sx / (float)physicalWidth) * (virtualMaxX - virtualMinX);
    }
    

    You could then do the same for your Y axis, by substituting the appropriate variable names. These could be optimized by pre-computing and caching some of the terms, and converting divisions by pre-computed terms to multiplications. Be-ware that you might have to re-compute cached terms if your window changes dimensions.

    You should also care about aspect ratio. To do this, you pick your “main” axis, usually Y, and then you scale your virtual ranges on the other axis by this aspect ratio.

    Like so:

    const float virtualMinY = -1.0f;
    const float virtualMaxY = 1.0f;
    
    const float aspect = physicalWidth / (float)physicalHeight;
    
    const float virtualMinX = -1.0f * aspect;
    const float virtualMaxX = 1.0f * aspect;
    

    Now, your function or sprite path will always look right, no matter what the aspect ratio is.

    It looks like you don’t really want to zoom, but anyways, for completeness, all you need to do to implement zoom, is to scale your virtual coordinate ranges (virtualMinX, virtualMaxX, virtualMinY, virtualMaxY) by your zoom factor.

    To zoom in 3x, your zoom factor is 1.0f / 3.0f.
    To zoom out 5x, it is 5.0f;

    (remember to recompute any cached values after changing zoom levels)

  2. If you want to “scale” the function you should change your input range ( or in mathematical terminology the domain of the function ). I advise you to make your domain irrelevant to the screen size. Also in order to make your display irrelevant of the the screen size you should use normalized coordinates ( e.x [-1…1] or [0…1] ). Screen coordinates normalization is very easy, you just divide your coordinates with the size of the screen.

  3. TheNickmaster21 on November 30, -0001 @ 12:00 AM

    Just find what the value will be when f(x) is out of your screen vertically. Then, scale the screen to that x value.

    So, just start at the middle of your function and find when the f(x) value is out of your bounds of your screen and scale it to there.

Leave a Reply