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

Javascript 如何将矩阵的旋转设置为给定点周围弧度的绝对值?,javascript,matrix,rotation,affinetransform,Javascript,Matrix,Rotation,Affinetransform,我有一个用于仿射变换的javascript矩阵类,以及一个函数,用于将旋转设置为围绕给定中心的绝对弧度数: 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.

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

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

如果我的对象从零旋转开始,则此操作正常:

。。。但是,如果我再次旋转形状,或者以非零的旋转开始,tx和ty值将以错误结束:

我上面的公式怎么了?设置旋转似乎是准确的,但不是tx和ty

在这个问题上,我还看到了一些其他问题,特别是一个,但没有任何帮助

更新为此添加一些数字:

如果我从一个100x100的矩形开始,定位在100100,那么我的初始矩阵是:
{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]}
(新的旋转形状的中心),尝试将它返回到零,那么输出是
{matrix:[a:1,b:0,c:0,d:1,tx:150,ty:79.28932188]}
,,这是正确的旋转,但不是正确的平移。我希望得到
{Matrix:[a:1,b:0,c:0,d:1,tx:100,ty:100]}

我尝试了该函数的其他几种变体,包括使用父坐标空间150150中矩形的中心,而不是局部中心50,50,以及将+=替换为=,如下所示,但似乎没有任何帮助。如果我注释掉tx计算,那么我的形状会围绕其原点漂亮地旋转,因此问题必须与tx/ty计算有关,或者与我要传递的中心点有关


有人有进一步的想法吗?

除了可能的错误符号之外(尽管这取决于坐标轴的方向),我认为问题很简单,当您填写仿射矩阵的
tx
ty
部分时,您使用的是
+=
而不是

除了可能的错误符号之外(尽管这取决于坐标轴的方向),我认为问题很简单,当你填写仿射矩阵的
tx
ty
部分时,你使用的是
+=
而不是

我的问题是将对象恢复到原点-在旋转之前移除左上角坐标以及一半的高度和宽度,然后再次添加它们

我发现使用rotate函数比使用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);

如果你真的能做加法的话,所有这些都很明显,但我把它贴在这里,以防有人有像我一样暗淡的一天…

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

我发现使用rotate函数比使用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);

如果你真的能做算术的话,所有这些都很明显,但我把它贴在这里,以防有人有像我一样暗淡的一天…

谢谢,但这并不能解决问题。符号被反转以匹配Adobe tools,因此顺时针45度为-45。@JcFx更改
+=
没有修复它?@JcFx也看到没有,没有。我不是围绕点旋转,而是尝试将旋转设置为特定值,如paper.js包含的setToRotation()函数。您的代码显然是在尝试围绕点旋转。如果你想设置一个不以原点为中心的基本体的方向,那就是你必须要做的。谢谢,但这并不能解决它。符号被反转以匹配Adobe tools,因此顺时针45度为-45。@JcFx更改
+=
没有修复它?@JcFx也看到没有,没有。我不是围绕点旋转,而是尝试将旋转设置为特定值,如paper.js包含的setToRotation()函数。您的代码显然是在尝试围绕点旋转。如果要设置不以原点为中心的基本体的方向,必须这样做。