# rotating a 2d square into another

I have two squares, S1 = (x1,y1,x2,y2) and S2 = (a1,b1,a2,b2)

I'm looking for the A transformation matrix with which A * S1 = S2

As far as I see, A is an affine 3x3 matrix, so I have 9 unknown values.

How can I calculate these values?

thanks and best, Viktor

## Answers

A transformation matrix is a factor of scaling matrix Ss, transition matrix St and rotation matrix Sr.

Assume the old point is Po is (Xo,Yo) and as vector will be represented as (Xo Yo 1)' same for the new point Pn
Then Pnv =Ss*St*SrPov
Where Sx is

Sx 0 0 0 Sy 0 0 0 1

St is

1 0 Tx 0 1 Ty 0 0 1

Sr is

Cos(th) -Sin(th) 0 Sin(th) Cos(th) 0 0 0 1

Now back to your question. if two point are giving to represent a rectangle we can just find the parameter of two matrix and the third one will be an identity matrix.

Rect1 is represented as Top-Left point P11 and Bottom-Right Point P12 Rect2 is represented as Top-Left point P21 and Bottom-Right Point P22

S=Ss*St

Sx 0 Tx 0 Sy Ty 0 0 1

Now you have 4 missing parameters and 4 set of equations

P21=S*P11 P22=S*P12 X[P21] =Sx*X[P11]+Tx Y[P21] =Sy*Y[P11]+Ty X[P22] =Sx*X[P12]+Tx Y[P22] =Sy*Y[P12]+Ty

Solve it and you'll get your answer.

and if you have transition and rotation then S=Sr*St.

Cos(th) -Sin(th) Tx Sin(th) Cos(th) Ty 0 0 1

Now you have 3 missing parameters and 4 set of equations

P21=S*P11 P22=S*P12 X[P21] =Cos(th)*X[P11]-Sin(th)*Y[P11]+Tx Y[P21] =Sin(th)*X[P11]+Cos(th)*Y[P11]+Ty X[P22] =Cos(th)*X[P11]-Sin(th)*Y[P12]+Tx Y[P22] =Sin(th)*X[P11]+Cos(th)*Y[P12]+Ty

Replace Cos(th) with A and Sin(th) With B and solve the equations.

X[P21] =A*X[P11]-B*Y[P11]+Tx Y[P21] =B*X[P11]+A*Y[P11]+Ty X[P22] =A*X[P11]-B*Y[P12]+Tx Y[P22] =B*X[P11]+A*Y[P12]+Ty

Check if its correct A^2+B^2 =? 1 if is true then th = aCos(A)

The last part of the solution, if you'll have all three matrixes, then S=Sr*St*Ss is

Sx*sin(th) -Sx*cos(th) Tx Sy*cos(th) Sy*sin(th) Ty 0 0 1

Now we have 5 missing variables and we need 6 different set of equations to solve it. which is mean 3 points from each rectangle.

There are really only four unknown values here. A rotation angle, a scale factor and an x and y translation. Of your three by three matrix the bottom row is always 0,0,1 which reduces you to six unknowns. The right hand column will be Tx,Ty,1 which are your translations (and the 1 we already know about).

The two by two "matrix" left will be your rotation and scaling. This will (off the top of my head) be something like:

ACos(B), -Asin(B) ASin(B), aCos(B)

So in total:

ACos(B), -Asin(B), Tx ASin(B), ACos(B), Ty 0 , 0 , 1

You extend your co-ordinate matrices with the 1 on the end of each co-ordinate to give 2x3 matrices and they then multiply to give you the four equations you need to solve for the four variables. That is left as an exercise for the reader.

You shouldn't have a 3x3 matrix if you're just looking to transform a 2D object. What you're looking for is a 2x2 matrix that solves A*S1=S2. This can be done in many different ways; in MATLAB, you'd do a S2/S1 (right matrix division), and generally this performs some kind of Gaussian elimination.

How can I calculate these values?

When applied to 2d/3d transformations, matrix can be represented a coordinate system, unless we are talking about projections.

Matrix rows (or columns, depending on notation) form axes of a new coordinate system, in which object will be placed placed if every object vertex is multiplied by the matrix. Last row (or columne, depending on notation) points to the center of the new coordinate system.

Standard OpenGL/DirectX transformation matrix (NOT a projection matrix):

class Matrix{//C++ code public: union{ float f[16]; float m[4][4]; }; };

Can be represented as combination of 4 vectors vx (x axis of the new coordinate system), vy(y axis of a new coordinate system), vz(z axis of a new coordinate system), and vp (center of the new system). Like this:

vx.x vx.y vx.z 0 vy.x vy.y vy.z 0 vz.x vz.y vz.z 0 vp.x vp.y vp.z 1

All "calculate rotation matrix", "calculate scale matrix", etc go down to this idea.

Thus, for 2d matrix, you'll have 3x3 matrix that consists of 3 vectors - vx, vy, vp, because there is no z vector in 2d. I.e.:

vx.x vx.y 0 vy.x vy.y 0 vp.x vp.y 1

To find a transform that would transform quad A into quad B, you need to find two transforms:

- Transform that will move quad A into origin (i.e. at point zero), and convert it into quad of fixed size. Say, quad (rectangle) whose one vertex x = 0, y = 0, and whose vertices are located at (0, 1), (1, 0), (1, 1).
- Transform that turns quad of fixed size into quad B.

You CANNOT do that it this way if opposite edges of quad are not parallel. I.e. parallelograms are fine, but random 4-sided polygons are not.

A quad can be represented by base point (vp) which can be any vertex of the quad and two vectors that define quad sizes (direction of the edge multiplied by edge's length). I.e. "up" vector and "side" vector. Which makes it a matrix:

side.x side.y 0 up.x up.y 0 vp.x vp.y 1

So, multiplying a quad (vp.x = 0, vp.y = 0, side.x = 1, side.y = 0, up.x = 0, up.y = 1) by this matrix will turn original quad into your quad. Which means, that in order to transform quad A into quad B, you need to do this:

1) make a matrix that would transform "base 1unit quad" into quad A. Let's call it matA. 2) make a matrix that would transform "base 1 unit quad" into quad B. let's call it matB. 3) invert matA and store result into invMatA. 4) the result matrix is invMatA * matB.

Done. If you multiply quad A by result matrix, you'll get quad B. This won't work if quads have zero widths or heights, and it won't work if quads are not parallelograms.

This is hard to understand, but I cannot to make it simpler.

What do you mean by S1 = (x1,y1,x2,y2)?

Do they represent the top-left and bottom-right corners of the square?

Also, can you guarantee there's only rotation between the squares or do you need a full affine transformation which allows for scaling, skewing, and translation?

Or do you also need a perspective transformation?

Only if it's a perspective transformation, will you need 3x3 matrix with 8 dof as you've mentioned in your post.