Question

I seem to be having a bit of a math fail here... I need to convert an (x,y) point from one coordinate space to another - not in the sense of polar to cartesian or anything of the sort... just from one bound to another. i.e., for a particular (x,y) that falls in the rectangle with lower left (-100, -100) and upper right (100,100), I need to find out where that point would be in a rectangle with lower left (0,0) and upper right (500, 500).

I feel like this is just simple math but I'm having a heck of a time getting it right...

It is for a little computer graphics program written in java. Essentially there is a clip window that changes, and that clip window needs to fill the whole view window. Initial values for clip and view are given by the above rectangles, in that order. However, the clip could change to, for example, a rectangle with lower left (-80, -65) and upper right (75, 65). I would then need to convert a point that falls within that rectangle to a point that falls within the view window (lower left (0,0), upper right (500, 500))

Here is what I have for it right now:

public int normalizeX(float x) {
    float clipWidth = clipRight - clipLeft;
    int viewWidth = viewRight - viewLeft;
    x += 100; //Get x into range [0, 200] instead of [-100, 100]
    //First convert x to value within clip width, then "scale" to viewport width
    return (int)(((clipWidth*x)/200) * (viewWidth/clipWidth));
}

public int normalizeY(float y) {
    float clipHeight = clipTop - clipBottom;
    int viewHeight = viewTop - viewBottom;
    y += 100; //Get y into range [0, 200] instead of [-100, 100]
    //First convert y to value within clip height, then "scale" to viewport height
    return (int)(((clipHeight*y)/200) * (viewHeight/clipHeight));
}

Thanks for any help!

Was it helpful?

Solution

Assuming your old bounds are xLoOld and xHiOld (-80 and 75, respectively, in your example) and your new bounds are xLoNew and xHiNew (0 and 500, respectively, in your example), then you can normalize your xOld to your new coordinate system like this:

xNew = (xOld-xLoOld) / (xHiOld-xLoOld) * (xHiNew-xLoNew) + xLoNew

Same thing for y.

OTHER TIPS

Something like this may help you.

    public static float scale(
           float x,
           float old_min, float old_max,
           float new_min, float new_max)
    {
        float old_range = old_max - old_min;
        float new_range = new_max - new_min;
        return new_min + (x - old_min) * new_range / old_range;
    }

You will need to scale your coordinates in both dimensions. I've left out other computations such as casting to int, etc.

I also recommend creating suitable types such as Region or Rectangle to simplify your code by, at least, reducing the number of arguments to this function.

Simple as hell: you want a transformation which maps -100 to 0 and 100 to 500. Or put blindly, which maps the range [-100, 100] to the range [0, 500] :

[-100, 100] ----> [0, 500]

First step is to convert the range [-100, 100] to [0, 200]:

x ----> x + 100

Next step is to convert the range [0, 200] to [0, 500]

x ----> x * 500 / 200 = 2.5 * x

In fine, your transformation reads

x ----> 2.5 * (x + 100) 

and likewise for y:

y ----> 2.5 * (y + 100).

Hope this makes it clear, and that you will be able to reuse the logic in more complex cases.

The slick and general way to do this is with an affine transform. You'll have a 2 x 2 matrix (call it A) that characterizes the "stretchiness" of the original field to the second field, and a 2 x 1 matrix (call it b) characterizing the offset.

Then, with x as your (2 x 1) input and y as your (2 x 1) output, it's just y = Ax + b.

The technique also lets you do a lot more (like rotations) but those probably aren't important for your application.

http://en.wikipedia.org/wiki/Affine_transformation

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top