2

Given 3 points (x and y coordinates) in coordinate system A, and 3 corresponding points in coordinate system B, how can I derive an AffineTransform that will convert from A to B.

My question is similar to Create transform to map from one rectangle to another?, except that question only deals with 2 points - i.e., it assumes there is no rotation.

Community
  • 1
  • 1
Todd Gibson
  • 1,005
  • 7
  • 16
  • Hint: express your transformation as a 3x2 matrix. To solve for its entries, you'll end up having to invert a 3x3 matrix. If nobody else posts an answer, I'll try to find some time later. – Dawood ibn Kareem Jan 21 '14 at 23:13

2 Answers2

3

Suppose your transform is of the form

x' = px + qy + r
y' = sx + ty + u

and write your six points as (A1x, A1y), (A2x, A2y), (A3x, A3y), (B1x, B1y), (B2x, B2y), (B3x, B3y). Expressing this in matrix form gives

/               \       /           \   /               \
| B1x  B2x  B3x |       | p   q   r |   | A1x  A2x  A3x |
|               |   =   |           |   |               |
| B1y  B2y  B3y |       | s   t   u |   | A1y  A2y  A3y |
\               /       \           /   |               |
                                        |  1    1    1  |
                                        \               /

Now find the inverse of the 3x3 matrix on the right. You'll find plenty of algorithms online telling you how to do this. There's one at http://www.econ.umn.edu/undergrad/math/An%20Algorithm%20for%20Finding%20the%20Inverse.pdf, for example.

Post-multiply both sides of the equation above by the inverse of the 3x3 matrix, to get the values of p, q, r, s, t, u, v.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • Thanks for your answer, but the matrix stuff is a bit of a mystery to me. Is it possible to provide an example of Java code that would build an AffineTransform object? Or if not that, do you know of any tutorial that starts from the basics? The information I've been able to find so far either starts right off with matrices (and loses me immediately), or it only deals with straightforward uses of the AffineTransform methods. – Todd Gibson Jan 22 '14 at 14:11
  • You're asking me for a LOT of code there. But the key point is finding the inverse of the 3x3 matrix. Why don't you either find a library that will do that, or start working on converting the algorithm that I linked to into code? – Dawood ibn Kareem Jan 22 '14 at 16:48
  • Am I correct in thinking I can use Apache commons-math library to do the matrix inversion and multiplication, then use that result in the AffineTransform constructor? – Todd Gibson Jan 22 '14 at 17:54
  • I don't know. Probably. I've never used it. – Dawood ibn Kareem Jan 22 '14 at 18:05
2

In case this is useful to anyone else, here is the Java code I used to do this.

    public static AffineTransform deriveAffineTransform(
        double oldX1, double oldY1,
        double oldX2, double oldY2,
        double oldX3, double oldY3,
        double newX1, double newY1,
        double newX2, double newY2,
        double newX3, double newY3) {

    double[][] oldData = { {oldX1, oldX2, oldX3}, {oldY1, oldY2, oldY3}, {1, 1, 1} };
    RealMatrix oldMatrix = MatrixUtils.createRealMatrix(oldData);

    double[][] newData = { {newX1, newX2, newX3}, {newY1, newY2, newY3} };
    RealMatrix newMatrix = MatrixUtils.createRealMatrix(newData);

    RealMatrix inverseOld = new LUDecomposition(oldMatrix).getSolver().getInverse();
    RealMatrix transformationMatrix = newMatrix.multiply(inverseOld);

    double m00 = transformationMatrix.getEntry(0, 0);
    double m01 = transformationMatrix.getEntry(0, 1);
    double m02 = transformationMatrix.getEntry(0, 2);
    double m10 = transformationMatrix.getEntry(1, 0);
    double m11 = transformationMatrix.getEntry(1, 1);
    double m12 = transformationMatrix.getEntry(1, 2);

    return new AffineTransform(m00, m10, m01, m11, m02, m12);       
}
Todd Gibson
  • 1,005
  • 7
  • 16