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 to have to edit a matrix directly. Is it possible to decompose a 3x2 matrix into scaling, rotation, skewing, and translation?
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 );
if 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With