分解二维变换矩阵
Decompose 2D Transformation Matrix
因此,我有一个 Direct2D Matrix3x2F
用于存储几何变换。我希望这些转换是用户可编辑的,我不希望用户必须直接编辑矩阵。是否可以将 3x2 矩阵分解为缩放、旋转、倾斜和平移?
将主要转换存储在具有可编辑属性的class中
scaling
rotation
skewing
translation
然后从中构建最终的变换矩阵。那样会更容易。但是,如果您必须有分解矩阵的算法。它们并不像你想象的那么简单。
System.Numerics有分解3D变换矩阵的方法
分解
是的,你可以(至少部分)。 3x2
变换矩阵表示没有投影的 2D 齐次 3x3 变换矩阵。这样的变换矩阵要么是 OpenGL 风格:
| Xx Yx Ox |
| Xy Yy Oy |
或DirectX风格:
| Xx Xy |
| Yx Yy |
| Ox Oy |
当你标记 Direct2D 并使用 3x2
矩阵时,第二个就是你得到的那个。有 3
个向量:
X=(Xx,Xy)
X
轴矢量
Y=(Yx,Yy)
Y
轴矢量
O=(Ox,Oy)
坐标系原点。
现在假设不存在偏斜并且矩阵是 正交...
缩放
非常简单,只需获取轴基向量长度即可。
scalex = sqrt( Xx^2 + Xy^2 );
scaley = sqrt( Yx^2 + Yy^2 );
是比例系数是 >1
矩阵放大,如果 <1
缩小。
旋转
您可以使用:
rotation_ang=atan2(Xy,Yx);
翻译
偏移量是 O
,因此如果它不为零,则表示存在翻译。
倾斜
在 2D 中,偏斜不会使事情过于复杂,上面的要点仍然适用(3D 情况并非如此)。倾斜角度是轴之间的角度减去 90
度,所以:
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;
另请注意,如果您的变换矩阵不代表您的坐标系而是它的逆矩阵,那么您需要在应用此矩阵之前对您的矩阵求逆...
所以计算第一个逆:
| Xx Xy 0 |
| Yx Yy 0 |
| Ox Oy 1 |
并对结果应用上述方法。
有关此主题的更多信息,请参阅:
特别是列主要顺序和行主要顺序之间的区别(OpenGL vs. DirectX 表示法)
这是我为 Direct2D 转换矩阵找到的解决方案:
比例 x = sqrt(M11 * M11 + M12 * M12)
缩放 y = sqrt(M21 * M21 + M22 * M22) * cos(shear)
旋转=atan2(M12, M11)
剪切 (y) = atan2(M22, M21) - PI/2 - rotation
翻译 x = M31
翻译y=M32
如果您按 scale(x, y) * skew(0, shear) * rotate(angle) * translate(x, y)
的顺序将这些值相乘,您将得到一个执行等效变换的矩阵。
因此,我有一个 Direct2D Matrix3x2F
用于存储几何变换。我希望这些转换是用户可编辑的,我不希望用户必须直接编辑矩阵。是否可以将 3x2 矩阵分解为缩放、旋转、倾斜和平移?
将主要转换存储在具有可编辑属性的class中
scaling
rotation
skewing
translation
然后从中构建最终的变换矩阵。那样会更容易。但是,如果您必须有分解矩阵的算法。它们并不像你想象的那么简单。
System.Numerics有分解3D变换矩阵的方法
分解
是的,你可以(至少部分)。
3x2
变换矩阵表示没有投影的 2D 齐次 3x3 变换矩阵。这样的变换矩阵要么是 OpenGL 风格:| Xx Yx Ox | | Xy Yy Oy |
或DirectX风格:
| Xx Xy | | Yx Yy | | Ox Oy |
当你标记 Direct2D 并使用
3x2
矩阵时,第二个就是你得到的那个。有3
个向量:X=(Xx,Xy)
X
轴矢量
Y=(Yx,Yy)
Y
轴矢量
O=(Ox,Oy)
坐标系原点。现在假设不存在偏斜并且矩阵是 正交...
缩放
非常简单,只需获取轴基向量长度即可。
scalex = sqrt( Xx^2 + Xy^2 ); scaley = sqrt( Yx^2 + Yy^2 );
是比例系数是
>1
矩阵放大,如果<1
缩小。旋转
您可以使用:
rotation_ang=atan2(Xy,Yx);
翻译
偏移量是
O
,因此如果它不为零,则表示存在翻译。倾斜
在 2D 中,偏斜不会使事情过于复杂,上面的要点仍然适用(3D 情况并非如此)。倾斜角度是轴之间的角度减去
90
度,所以: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;
另请注意,如果您的变换矩阵不代表您的坐标系而是它的逆矩阵,那么您需要在应用此矩阵之前对您的矩阵求逆...
所以计算第一个逆:
| Xx Xy 0 |
| Yx Yy 0 |
| Ox Oy 1 |
并对结果应用上述方法。
有关此主题的更多信息,请参阅:
特别是列主要顺序和行主要顺序之间的区别(OpenGL vs. DirectX 表示法)
这是我为 Direct2D 转换矩阵找到的解决方案:
比例 x =
sqrt(M11 * M11 + M12 * M12)
缩放 y =
sqrt(M21 * M21 + M22 * M22) * cos(shear)
旋转=
atan2(M12, M11)
剪切 (y) =
atan2(M22, M21) - PI/2 - rotation
翻译 x =
M31
翻译y=
M32
如果您按 scale(x, y) * skew(0, shear) * rotate(angle) * translate(x, y)
的顺序将这些值相乘,您将得到一个执行等效变换的矩阵。