如何将矩阵的旋转设置为给定点周围的弧度的绝对值?

时间:2012-09-26 11:46:10

标签: javascript matrix rotation affinetransform

我有一个用于仿射变换的javascript Matrix类,以及一个将旋转设置为围绕给定中心的绝对弧度数的函数:

this.setRotation = function (radians, center) {
    var cos = Math.cos(radians);
    var sin = Math.sin(radians);
    this.a = cos;
    this.b = sin;
    this.c = -sin;
    this.d = cos;
    this.tx += center.x - center.x * cos + center.y * sin;
    this.ty += center.y - center.x * sin - center.y * cos;
}

我试图围绕物体的中心旋转,所以我在物体宽度的一半和高度的一半的中心点通过,所以对于一个100 x 100的物体,我正在经过50 ,50。

如果我的对象从零旋转开始,这可以正常工作:

Before After

...但是如果我再次旋转形状,或者以非0的旋转开始,则tx和ty值最终会出错:

Position moved

上面的公式出了什么问题?设置旋转似乎是准确的,但不是tx和ty。

我已经看到了关于这个主题的一些其他问题,特别是this一个,但没有任何帮助。

更新要为此添加一些数字:

如果我从一个100x100的矩形开始,位于100,100,那么我的初始矩阵为:{Matrix: [a:1, b:0, c:0, d:1, tx:100, ty:100]}

要顺时针旋转45度,我需要输入上面的函数0.7853981633974483(弧度45度),中心:{Point: [x:50, y: 50]}

这会产生以下矩阵: {Matrix: [a:0.7071067812, b:0.7071067812, c:-0.7071067812, d:0.7071067812, tx:150, ty:79.28932188]}这是完全正确的。

但是如果我然后从那个矩阵开始,并尝试将它返回到零,通过提供0和{Point: [x:70.71067812000001, y: 70.71067812000001]}的函数参数(新的旋转形状的中心),则输出为{{ 1}},这是正确的旋转,但不是正确的翻译。我期待得到{Matrix: [a:1, b:0, c:0, d:1, tx:150, ty:79.28932188]}

我已经尝试了该函数的其他几个变体,包括在父坐标空间150,150中使用矩形的中心而不是50,50的局部中心,并且如下所示替换+ = with =,但似乎没有帮助。如果我注释掉tx计算,那么我的形状会围绕它的原点漂移,所以问题必须是tx / ty计算,或者是我传入的中心点。

有没有人有任何进一步的想法?

2 个答案:

答案 0 :(得分:1)

除了可能是一个不正确的符号(虽然这取决于您的坐标轴的方向),我认为问题只是当您填写时,您正在使用+=而不是= <仿真矩阵的txty部分。

答案 1 :(得分:0)

我的问题是将物体放回原点 - 在旋转之前移除左上角坐标以及高度和宽度的一半,然后再将它们添加回去。

我发现使用旋转功能比使用setRotate功能更容易,最后得到以下代码:

// Matrix class functions:
this.rotate = function (radians) {
    var cos = parseFloat(Math.cos(radians).toFixed(10));
    var sin = parseFloat(Math.sin(radians).toFixed(10));
    a = this.a,
    b = this.b,
    c = this.c,
    d = this.d,
    tx = this.tx,
    ty = this.ty;
    this.a = a * cos - b * sin;
    this.b = a * sin + b * cos;
    this.c = c * cos - d * sin;
    this.d = c * sin + d * cos;
    this.tx = tx * cos - ty * sin;
    this.ty = tx * sin + ty * cos;
}

this.setRotation = function (radians) {
    var rotation = this.rotation();
    this.rotate(radians - rotation);
}

this.translate = function (tx, ty) {
    this.tx += tx;
    this.ty += ty;
}

// Called from outside the class
var transformedBounds = pe.Model.ReadTransformedBounds(selection[0]);
var itemTransform = pe.Model.ReadItemTransform(selection[0]);

// Cache the coordinates before translating them away:
var ox = transformedBounds.Left + (transformedBounds.Width / 2); 
var oy = transformedBounds.Top + (transformedBounds.Height / 2);
itemTransform.translate(-ox, -oy);

// Rotate:
itemTransform.setRotation(radians);

// Restore the translation:
itemTransform.translate(ox, oy);

如果你真的可以做总结,那么所有这些都可能很明显,但我在这里发布以防万一有人像我一样昏暗的一天......