So, I have a Direct2D Matrix3x2F
that I use to store transformations on geometries. I want these transformations to be user-editable, and I don\'t want the user
This is the solution I found for a Direct2D transformation matrix:
scale x = sqrt(M11 * M11 + M12 * M12)
scale y = sqrt(M21 * M21 + M22 * M22) * cos(shear)
rotation = atan2(M12, M11)
shear (y) = atan2(M22, M21) - PI/2 - rotation
translation x = M31
translation y = M32
If you multiply these values back together in the order scale(x, y) * skew(0, shear) * rotate(angle) * translate(x, y)
you will get a matrix that performs an equivalent transformation.
Decomposition
yes you can (at least partially). 3x2
transform matrix represents 2D homogenuous 3x3 transform matrix without projections. Such transform matrix is either OpenGL style:
| Xx Yx Ox |
| Xy Yy Oy |
or DirectX style:
| Xx Xy |
| Yx Yy |
| Ox Oy |
As you tagged Direct2D and using 3x2
matrix then the second is the one you got. There are 3
vectors:
X=(Xx,Xy)
X
axis vector
Y=(Yx,Yy)
Y
axis vector
O=(Ox,Oy)
Origin of coordinate system.
Now lets assume that there is no skew present and the matrix is orthogonal...
Scaling
is very simple just obtain the axises basis vectors lengths.
scalex = sqrt( Xx^2 + Xy^2 );
scaley = sqrt( Yx^2 + Yy^2 );
is scale coefficient is >1
the matrix scales up and if <1
scales down.
rotation
You can use:
rotation_ang=atan2(Xy,Yx);
translation
The offset is O
so if it is non zero you got translation present.
Skew
In 2D skew does not complicate things too much and the bullets above still apply (not the case for 3D). The skew angle is the angle between axises minus 90
degrees so:
skew_angle = acos((X.Y)/(|X|.|Y|)) - 0.5*PI;
skew_angle = acos((Xx*Yx + Xy*Yy)/sqrt(( Xx^2 + Xy^2 )*( Yx^2 + Yy^2 ))) - 0.5*PI;
Also beware if your transform matrix does not represent your coordinate system but its inverse then you need to inverse your matrix before applying this...
So compute first inverse of:
| Xx Xy 0 |
| Yx Yy 0 |
| Ox Oy 1 |
And apply the above on the result.
For more info about this topic see:
Especially the difference between column major and row major orders (OpenGL vs. DirectX notation)
Store the primary transformations in a class with editable properites
scaling
rotation
skewing
translation
and then build the final transform matrix from those. It will be easier that way. However if you must there are algorithms for decomposing a matrix. They are not as simple as you might think.
System.Numerics has a method for decomposing 3D transform matrices
https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs#L1497