# Howto calculate an Affine-Transformation for two transformed points?

Hi,

I have a problem which challenges me a bit too much ;)

Basically I need exactly the opposite of what the AffineTransform class provides. Instead of transforming two points with a given transformation I would need to calculate the AffineTransform by comparing the result of a transformation.

I have two points (p1, p2) which located right below each other, e.g. p1(x=10, y=10) p2(x=10, y=40) and now I would need the AffineTransformation which would transform those two points to some other coordinates e.g.(x=10, y=20), (x=90, y=298).

Any idea howto do this?

Thanks, Clemens

The transform is specified by the equations in the AffineTransform docs:

x' = m00x + m01y + m02

y' = m10x + m11y + m12

You know two samples for the old (x,y) and new (x',y') values so you can solve for the m## values if you can generate 3 simultaneous equations in X and Y (i.e. you need 3 points to do the mapping). With your example, you can generate 2 equations each for each x:

10 = m00 * 10 + m01 * 10 + m02

90 = m00 * 10 + m01 * 40 + m02

and y:

20 = m10 * 10 + m11 * 10 + m12

298 = m10 * 10 + m11 * 40 + m12

You either need another pair of before/after points to generate another equation for each system to solve it, or you can assume something about the solution (such as assume m02 and m12 are both 0) and solve it with just 2 points yielding (in this case with this assumption) a transform that has no translation components.

There are lots of articles on the web that show how to solve simultaneous equations in software...

Example using Apache commons math library for matrix calculations

import java.awt.geom.AffineTransform;

import java.awt.geom.Point2D;

import org.apache.commons.math.linear.Array2DRowRealMatrix;

import org.apache.commons.math.linear.LUDecompositionImpl;

public class GraphicsMath {

public static AffineTransform calculateTransform(Point2D src[], Point2D dst[]) {

Array2DRowRealMatrix x = new Array2DRowRealMatrix(new double[][] {

{ src[0].getX(), src[1].getX(), src[2].getX() }, { src[0].getY(), src[1].getY(), src[2].getY() },

{ 1, 1, 1 } });

Array2DRowRealMatrix y = new Array2DRowRealMatrix(new double[][] {

{ dst[0].getX(), dst[1].getX(), dst[2].getX() }, { dst[0].getY(), dst[1].getY(), dst[2].getY() },

{ 0, 0, 0 } });

double[][] data = y.multiply(new LUDecompositionImpl(x).getSolver().getInverse()).getData();

return new AffineTransform(

new double[] { data[0][0], data[1][0], data[0][1], data[1][1], data[0][2], data[1][2] });

}

public static void main(String[] args) {

Point2D src[] = new Point2D[] { new Point2D.Double(0, 0), new Point2D.Double(1, 0), new Point2D.Double(0, 1) };

Point2D dst[] = new Point2D[] { new Point2D.Double(0, 0), new Point2D.Double(1, .5), new Point2D.Double(-1, .5) };

AffineTransform t = GraphicsMath.calculateTransform(src, dst);

System.out.println(t);

System.out.println(t.transform(new Point2D.Double(0, 0), null));

System.out.println(t.transform(new Point2D.Double(1, 0), null));

System.out.println(t.transform(new Point2D.Double(0, 1), null));

}

}

output:

AffineTransform[[1.0, -1.0, 0.0], [0.5, 0.5, 0.0]]

Point2D.Double[0.0, 0.0]

Point2D.Double[1.0, 0.5]

Point2D.Double[-1.0, 0.5]