Decompose 2D Transformation Matrix

后端 未结 3 905
余生分开走
余生分开走 2021-01-03 09:49

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

相关标签:
3条回答
  • 2021-01-03 10:18

    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.

    0 讨论(0)
  • 2021-01-03 10:20
    1. 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...

    2. 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.

    3. rotation

      You can use:

      rotation_ang=atan2(Xy,Yx);
      
    4. translation

      The offset is O so if it is non zero you got translation present.

    5. 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:

    • Understanding 4x4 homogenous transform matrices

    Especially the difference between column major and row major orders (OpenGL vs. DirectX notation)

    0 讨论(0)
  • 2021-01-03 10:35

    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

    0 讨论(0)
提交回复
热议问题