extract rotation, scale values from 2d transformation matrix

后端 未结 4 1988
野性不改
野性不改 2020-11-30 20:24

how can i extract rotation, scale and translation values from 2d transformation matrix? i mean a have a 2d transformation

matrix = [1, 0, 0, 1, 0, 0]

matri         


        
相关标签:
4条回答
  • 2020-11-30 21:01

    Not all values of a,b,c,d,tx,ty will yield a valid rotation sequence. I assume the above values are part of a 3x3 homogeneous rotation matrix in 2D

        | a  b  tx |
    A = | c  d  ty |
        | 0  0  1  |
    

    which transforms the coordinates [x, y, 1] into:

    [x', y', 1] = A * |x|
                      |y|
                      |z|
    
    • Thus set the traslation into [dx, dy]=[tx, ty]
    • The scale is sx = sqrt(a² + c²) and sy = sqrt(b² + d²)
    • The rotation angle is t = atan(c/d) or t = atan(-b/a) as also they should be the same.

    Otherwise you don't have a valid rotation matrix.


    The above transformation is expanded to:

    x' = tx + sx (x Cos θ - y Sin θ)
    y' = ty + sy (x Sin θ + y Cos θ)
    

    when the order is rotation, followed by scale and then translation.

    0 讨论(0)
  • 2020-11-30 21:02

    I ran into this problem today and found the easiest solution to transform a point using the matrix. This way, you can extract the translation first, then rotation and scaling.

    This only works if x and y are always scaled the same (uniform scaling).

    Given your matrix m which has undergone a series of transforms,

    var translate:Point;
    var rotate:Number;
    var scale:Number;
    
    // extract translation
    var p:Point = new Point();
    translate = m.transformPoint(p);
    m.translate( -translate.x, -translate.y);
    
    // extract (uniform) scale
    p.x = 1.0;
    p.y = 0.0;
    p = m.transformPoint(p);
    scale = p.length;
    
    // and rotation
    rotate = Math.atan2(p.y, p.x);
    

    There you go!

    0 讨论(0)
  • 2020-11-30 21:03

    The term for this is matrix decomposition. Here is a solution that includes skew as described by Frédéric Wang.

    function decompose_2d_matrix(mat) {
      var a = mat[0];
      var b = mat[1];
      var c = mat[2];
      var d = mat[3];
      var e = mat[4];
      var f = mat[5];
    
      var delta = a * d - b * c;
    
      let result = {
        translation: [e, f],
        rotation: 0,
        scale: [0, 0],
        skew: [0, 0],
      };
    
      // Apply the QR-like decomposition.
      if (a != 0 || b != 0) {
        var r = Math.sqrt(a * a + b * b);
        result.rotation = b > 0 ? Math.acos(a / r) : -Math.acos(a / r);
        result.scale = [r, delta / r];
        result.skew = [Math.atan((a * c + b * d) / (r * r)), 0];
      } else if (c != 0 || d != 0) {
        var s = Math.sqrt(c * c + d * d);
        result.rotation =
          Math.PI / 2 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s));
        result.scale = [delta / s, s];
        result.skew = [0, Math.atan((a * c + b * d) / (s * s))];
      } else {
        // a = b = c = d = 0
      }
    
      return result;
    }
    
    0 讨论(0)
  • 2020-11-30 21:04

    If in scaling you'd scaled by the same amount in x and in y, then the determinant of the matrix, i.e. ad-bc, which tells you the area multiplier would tell you the linear change of scale too - it would be the square root of the determinant. atan( b/a ) or better atan2( b,a ) would tell you the total angle you have rotated through.

    However, as your scaling isn't uniform, there is usually not going to be a way to condense your series of rotations and scaling to a single rotation followed by a single non-uniform scaling in x and y.

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