Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create transform to map from one rectangle to another?

What is the simplest way to create AffineTransform which maps coordinates from one rectangle to another (float/double rectangles are given)?

UPDATE 1

Rectangles can be absolutely different. For example [(0,0)-(1,1)] and [(150,-14)-(-1000,-14.1)]. And transformation should transform uniformly. For example, rectangle corners should be transformed one to one. For example coordinates (0,0) should turn to (150,-14).

UPDATE 2

I need AffineTransform object, not just calculation. Because I want to apply it to Graphics object. Also I would like to have in the form of some concatenation of simple transforms.

UPDATE 3

All the following 3 tests are failed:

public class RectangleTransformTest {

    private static final double delta = 0.001;

    Rectangle2D r1 = new Rectangle2D.Double(-1, 0, 2, 0.01);
    Rectangle2D r2 = new Rectangle2D.Double(10, 20, 400, 300);

    AffineTransform t;

    Point2D src;
    Point2D dst1, dst2;

    @Test
    public void test1() {

        t = new AffineTransform();
        t.translate(+r2.getMinX()-r1.getMinX(), +r2.getMinY()-r1.getMinY());
        t.scale(r2.getWidth()/r1.getWidth(), r2.getHeight()/r1.getHeight());

    }

    @Test
    public void test2() {

        t = new AffineTransform();

        t.scale(r2.getWidth()/r1.getWidth(), r2.getHeight()/r1.getHeight());
        t.translate(+r2.getMinX()-r1.getMinX(), +r2.getMinY()-r1.getMinY());

    }

    @Test
    public void test3() {

        t = new AffineTransform();

        t.scale((r2.getMaxX()-r2.getMinX())/(r1.getMaxX()-r1.getMinX()), (r2.getMaxY()-r2.getMinY())/(r1.getMaxY()-r1.getMinY()));
        t.translate(+r2.getMinX()-r1.getMinX(), +r2.getMinY()-r1.getMinY());

    }

    @After
    public void comparePoints() {

        src = new Point2D.Double(r1.getMinX(), r1.getMinY());
        dst1 =  new Point2D.Double();
        t.transform(src, dst1);
        dst2 = new Point2D.Double(r2.getMinX(), r2.getMinY());

        assertEquals(dst2.getX(), dst1.getX(), delta);
        assertEquals(dst2.getY(), dst1.getY(), delta);

        src = new Point2D.Double(r1.getMinX(), r1.getMaxY());
        dst1 =  new Point2D.Double();
        t.transform(src, dst1);
        dst2 = new Point2D.Double(r2.getMinX(), r2.getMaxY());

        assertEquals(dst2.getX(), dst1.getX(), delta);
        assertEquals(dst2.getY(), dst1.getY(), delta);

        src = new Point2D.Double(r1.getMaxX(), r1.getMinY());
        dst1 =  new Point2D.Double();
        t.transform(src, dst1);
        dst2 = new Point2D.Double(r2.getMaxX(), r2.getMinY());

        assertEquals(dst2.getX(), dst1.getX(), delta);
        assertEquals(dst2.getY(), dst1.getY(), delta);

        src = new Point2D.Double(r1.getMaxX(), r1.getMaxY());
        dst1 =  new Point2D.Double();
        t.transform(src, dst1);
        dst2 = new Point2D.Double(r2.getMaxX(), r2.getMaxY());

        assertEquals(dst2.getX(), dst1.getX(), delta);
        assertEquals(dst2.getY(), dst1.getY(), delta);

    }

}
like image 830
Dims Avatar asked Dec 23 '12 23:12

Dims


1 Answers

To transform from [(a,b)-(c,d)] to [(e,f)-(g,h)] you can perform the following computation:

x' = e + (x - a) * (g - e) / (c - a);
y' = f + (y - b) * (h - f) / (d - b);

Here is the corresponding AffineTransform code, where r1 is being transformed to r2:

t = new AffineTransform();
t.translate(r2.getMinX(), r2.getMinY());
t.scale(r2.getWidth()/r1.getWidth(), r2.getHeight()/r1.getHeight());    
t.translate(-r1.getMinX(), -r1.getMinY());
like image 102
sam hocevar Avatar answered Sep 29 '22 13:09

sam hocevar