Skip to main content

Howto calculate an Affine-Transformation for two transformed points?

2 replies [Last post]
linuxhippy
Offline
Joined: 2004-01-07
Points: 0

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

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ischumacher
Offline
Joined: 2003-12-03
Points: 0

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]

flar
Offline
Joined: 2003-06-11
Points: 0

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...