分解二维变换矩阵

lap*_*tou 4 c# math direct2d

所以,我有一个 Direct2D Matrix3x2F,我用它来存储几何上的转换。我希望这些转换是用户可编辑的,并且我不希望用户必须直接编辑矩阵。是否可以将 3x2 矩阵分解为缩放、旋转、倾斜和平移?

lap*_*tou 7

这是我为 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)您将得到一个执行等效变换的矩阵。


Spe*_*tre 5

  1. 分解

    是的,你可以(至少部分)。 3x2变换矩阵表示没有投影的 2D 同质 3x3 变换矩阵。这样的变换矩阵可以是OpenGL风格:

     | Xx Yx Ox |
     | Xy Yy Oy |
    
    Run Code Online (Sandbox Code Playgroud)

    DirectX风格:

     | Xx Xy |
     | Yx Yy |
     | Ox Oy |
    
    Run Code Online (Sandbox Code Playgroud)

    当您标记Direct2D并使用3x2矩阵时,第二个就是您得到的。有3向量:


    X=(Xx,Xy) X轴向量
    Y=(Yx,Yy) Y轴向
    O=(Ox,Oy)量 坐标系的原点。

    现在假设不存在偏斜并且矩阵是正交的......

  2. 缩放

    非常简单,只需获取轴基向量长度即可。

     scalex = sqrt( Xx^2 + Xy^2 );
     scaley = sqrt( Yx^2 + Yy^2 );
    
    Run Code Online (Sandbox Code Playgroud)

    如果比例系数是>1矩阵则按比例放大,如果则按<1比例缩小。

  3. 回转

    您可以使用:

     rotation_ang=atan2(Xy,Yx);
    
    Run Code Online (Sandbox Code Playgroud)
  4. 翻译

    偏移量是O这样的,如果它不为零,则表示存在翻译。

  5. 倾斜

    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;
    
    Run Code Online (Sandbox Code Playgroud)

另请注意,如果您的变换矩阵不代表您的坐标系而是其逆矩阵,那么您需要在应用此矩阵之前反转您的矩阵...

因此计算第一个倒数:

| Xx Xy 0 |
| Yx Yy 0 |
| Ox Oy 1 |
Run Code Online (Sandbox Code Playgroud)

并将上述结果应用到结果上。

有关此主题的更多信息,请参阅:

特别是列主序和行主序之间的差异(OpenGLDirectX表示法)