我有一个用于仿射变换的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。
如果我的对象从零旋转开始,这可以正常工作:
...但是如果我再次旋转形状,或者以非0的旋转开始,则tx和ty值最终会出错:
上面的公式出了什么问题?设置旋转似乎是准确的,但不是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计算,或者是我传入的中心点。
有没有人有任何进一步的想法?
答案 0 :(得分:1)
除了可能是一个不正确的符号(虽然这取决于您的坐标轴的方向),我认为问题只是当您填写时,您正在使用+=
而不是=
<仿真矩阵的tx
和ty
部分。
答案 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);
如果你真的可以做总结,那么所有这些都可能很明显,但我在这里发布以防万一有人像我一样昏暗的一天......