从二维变换矩阵中提取旋转、缩放值

发布于 2024-10-06 11:27:36 字数 945 浏览 2 评论 0原文

如何从二维变换矩阵中提取旋转、缩放和平移值?我的意思是 a 有一个二维变换

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

matrix.rotate(45 / 180 * PI)
matrix.scale(3, 4)
matrix.translate(50, 100)
matrix.rotate(30 / 180 * PI)
matrix.scale(-2, 4)

,现在我的矩阵有值 [a, b, c, d, tx, ty]

让我们忘记上面的过程,想象我们只有值 a, b, c, d, tx, ty

我如何通过 a、b、c、d、tx、ty 找到总旋转和比例值

抱歉我的英语

谢谢您的提前

编辑

我认为这应该是某个地方的答案...

我刚刚尝试过在 Flash Builder (AS3) 中像这样

   var m:Matrix = new Matrix;
   m.rotate(.25 * Math.PI);
   m.scale(4, 5);
   m.translate(100, 50);
   m.rotate(.33 * Math.PI);
   m.scale(-3, 2.5);

   var shape:Shape = new Shape;
   shape.transform.matrix = m;

   trace(shape.x, shape.y, shape.scaleX, shape.scaleY, shape.rotation);

,输出是:

x = -23.6 
y = 278.8 
scaleX = 11.627334873920528 
scaleY = -13.54222263865791 
rotation = 65.56274134518259 (in degrees)

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]

matrix.rotate(45 / 180 * PI)
matrix.scale(3, 4)
matrix.translate(50, 100)
matrix.rotate(30 / 180 * PI)
matrix.scale(-2, 4)

now my matrix have values [a, b, c, d, tx, ty]

lets forget about the processes above and imagine that we have only the values a, b, c, d, tx, ty

how can i find total rotation and scale values via a, b, c, d, tx, ty

sorry for my english

Thanks your advance

EDIT

I think it should be an answer somewhere...

i just tried in Flash Builder (AS3) like this

   var m:Matrix = new Matrix;
   m.rotate(.25 * Math.PI);
   m.scale(4, 5);
   m.translate(100, 50);
   m.rotate(.33 * Math.PI);
   m.scale(-3, 2.5);

   var shape:Shape = new Shape;
   shape.transform.matrix = m;

   trace(shape.x, shape.y, shape.scaleX, shape.scaleY, shape.rotation);

and the output is:

x = -23.6 
y = 278.8 
scaleX = 11.627334873920528 
scaleY = -13.54222263865791 
rotation = 65.56274134518259 (in degrees)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

方觉久 2024-10-13 11:27:36

并非 a、b、c、d、tx、ty 的所有值都会产生有效的旋转序列。我假设上述值是 2D 3x3 齐次旋转矩阵的一部分

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

,它将坐标 [x, y, 1] 转换为:

[x', y', 1] = A * |x|
                  |y|
                  |z|
  • 因此将转换设置为 [dx, dy]=[ tx, ty]
  • 比例尺为 sx = sqrt(a² + c²)sy = sqrt(b² + d²)
  • 旋转角度为 t = atan(c/d)t = atan(-b/a) 因为它们也应该是相同的。

否则你就没有有效的旋转矩阵。


将上面的变换展开为:

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

当顺序是旋转时,先是缩放,再是平移。

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.

战皆罪 2024-10-13 11:27:36

我今天遇到了这个问题,并找到了使用矩阵变换点的最简单的解决方案。这样,您可以先提取平移,然后提取旋转和缩放。

仅当 x 和 y 始终缩放相同(均匀缩放)时,此方法才有效。

给定你的矩阵 m 已经经历了一系列的变换,

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);

你就可以了!

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!

伴我心暖 2024-10-13 11:27:36

这个术语是矩阵分解。这是一个包含倾斜的解决方案,如所述弗雷德里克·王

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;
}

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;
}
赠佳期 2024-10-13 11:27:36

如果在缩放时,您在 x 和 y 中缩放相同的量,那么矩阵的行列式,即 ad-bc,它告诉您面积乘数也会告诉您缩放的线性变化 - 它将是平方行列式的根。 atan( b/a ) 或更好的 atan2( b,a ) 会告诉您旋转的总角度。

然而,由于缩放不均匀,通常没有办法将一系列旋转和缩放压缩为单个旋转,然后在 x 和 y 上进行单个非均匀缩放。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文