分解二维变换矩阵

时间:2017-07-18 06:39:59

标签: c# math direct2d

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

3 个答案:

答案 0 :(得分:2)

  1. <强>分解

    是的,你可以(至少部分地)。 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)坐标系的起源。

    现在让我们假设没有歪斜,矩阵正交 ......

  2. <强>缩放

    非常简单,只需获取轴基矢量长度。

    scalex = sqrt( Xx^2 + Xy^2 );
    scaley = sqrt( Yx^2 + Yy^2 );
    

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

  3. 轮换

    您可以使用:

    rotation_ang=atan2(Xy,Yx);
    
  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;
    
  6. 另外要注意,如果您的变换矩阵不代表您的坐标系,而是它的逆矩阵,那么您需要在应用此矩阵之前反转矩阵...

    所以计算第一个逆:

    | Xx Xy 0 |
    | Yx Yy 0 |
    | Ox Oy 1 |
    

    并在结果上应用以上内容。

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

    特别是列主要订单和行主要订单之间的差异( OpenGL DirectX 表示法)

答案 1 :(得分:2)

这是我为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)的顺序将这些值相乘,您将得到一个执行等效转换的矩阵。

答案 2 :(得分:0)

将主要转换存储在具有可编辑属性的类中

   scaling
   rotation
   skewing
   translation

然后从那些构建最终的变换矩阵。这样会更容易。但是,如果必须有分解矩阵的算法。它们并不像你想象的那么简单。

System.Numerics有一种分解3D变换矩阵的方法

https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/src/System/Numerics/Matrix4x4.cs#L1497