绕任意轴旋转思路
中心轴与坐标轴平行
1.将旋转轴平移与坐标轴重合,物体也做平移操作;
2.物体绕坐标轴旋转;
3.执行步骤1的逆操作,将旋转轴平移回到原来位置,物体也对应平移;
中心轴与坐标轴不平行
可以参照上节的“中心轴与坐标轴平行”的做法,只是多一个步骤,将旋转轴旋转到与任意坐标轴平行,以及后面的逆操作;
具体步骤:
1.将旋转轴平移至原点;
2.将旋转轴旋转至YOZ平面;
3.将旋转轴旋转与Z轴重合;
4.物体绕Z轴旋转
θ
\theta
θ度;
5.执行步骤3,步骤2,步骤1的逆操作;
计算向量 v ⃗ \vec{v} v绕向量 a ⃗ \vec{a} a旋转 θ \theta θ度
向量
v
⃗
\vec{v}
v可以分解为向量
v
c
⃗
\vec{v_{c}}
vc与向量
v
1
⃗
\vec{v_{1}}
v1;
向量
v
1
⃗
\vec{v_{1}}
v1绕向量
a
⃗
\vec{a}
a旋转
θ
\theta
θ度后,得到向量
v
1
′
⃗
\vec{v_{1}'}
v1′;
我们最终的目标是计算得到向量
v
′
⃗
=
v
c
⃗
+
v
1
′
⃗
\vec{v'}=\vec{v_{c}}+\vec{v_{1}'}
v′=vc+v1′;
两个向量的初始值为:
α
⃗
=
{
α
x
,
α
y
,
α
z
}
\vec{\alpha }=\left \{ \alpha _{x} ,\alpha _{y},\alpha _{z}\right \}
α={αx,αy,αz}
v
⃗
=
{
v
x
,
v
y
,
v
z
}
\vec{v }=\left \{ v_{x} ,v_{y},v_{z}\right \}
v={vx,vy,vz}
具体的计算步骤如下:
1.计算得到向量
v
⃗
\vec{v}
v在向量
a
⃗
\vec{a}
a方向上的投影为:
v
c
⃗
=
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
\vec{v_{c}}=(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha }
vc=(v⋅α)⋅α
2.计算得到向量
v
1
⃗
\vec{v_{1}}
v1:
v
1
⃗
=
v
⃗
−
v
c
⃗
=
v
⃗
−
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
\vec{v_{1}}=\vec{v}-\vec{v_{c}}=\vec{v}-(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha }
v1=v−vc=v−(v⋅α)⋅α
由于
α
⃗
×
α
⃗
=
0
\vec{\alpha }\times\vec{\alpha }=0
α×α=0,则
v
2
⃗
\vec{v_{2}}
v2可以计算得到下式:
v
2
⃗
=
v
1
⃗
×
α
⃗
=
(
v
⃗
−
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
)
×
α
⃗
=
v
⃗
×
α
⃗
−
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
×
α
⃗
=
v
⃗
×
α
⃗
\vec{v_{2}}=\vec{v_{1}}\times \vec{\alpha }=(\vec{v}-(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha })\times\vec{\alpha }=\vec{v}\times\vec{\alpha }-(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha }\times\vec{\alpha }=\vec{v}\times\vec{\alpha }
v2=v1×α=(v−(v⋅α)⋅α)×α=v×α−(v⋅α)⋅α×α=v×α
3.计算得到
v
′
⃗
\vec{v'}
v′:
v
′
⃗
=
v
c
⃗
+
v
1
⃗
∗
c
o
s
θ
+
v
2
⃗
∗
s
i
n
θ
\vec{v'}=\vec{v_{c}}+\vec{v_{1}}*cos\theta +\vec{v_{2}}*sin\theta
v′=vc+v1∗cosθ+v2∗sinθ
=
v
c
⃗
+
v
1
⃗
∗
C
+
v
2
⃗
∗
S
=\vec{v_{c}}+\vec{v_{1}}*C +\vec{v_{2}}*S
=vc+v1∗C+v2∗S
=
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
+
(
v
⃗
−
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
)
∗
C
+
v
⃗
×
α
⃗
∗
S
=(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha }+(\vec{v}-(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha })*C+\vec{v}\times\vec{\alpha }*S
=(v⋅α)⋅α+(v−(v⋅α)⋅α)∗C+v×α∗S
=
v
⃗
∗
C
+
(
v
⃗
⋅
α
⃗
)
⋅
α
⃗
∗
(
1
−
C
)
+
v
⃗
×
α
⃗
∗
S
=\vec{v}*C+(\vec{v}\cdot \vec{\alpha })\cdot\vec{\alpha }*(1-C)+\vec{v}\times\vec{\alpha }*S
=v∗C+(v⋅α)⋅α∗(1−C)+v×α∗S
其中:C表示
c
o
s
θ
cos\theta
cosθ,S表示
s
i
n
θ
sin\theta
sinθ;
将组成对象坐标系的三个坐标轴,同时绕向量
a
⃗
\vec{a}
a旋转
θ
\theta
θ度,可以得到旋转后的方向矩阵:
该矩阵的详细推导,参见3D数学 ---- 矩阵和线性变换(1);
VTK中的旋转计算
void vtkTransformConcatenation::Rotate(double angle, double x, double y, double z)
{
if (angle == 0.0 || (x == 0.0 && y == 0.0 && z == 0.0))
{
return;
}
// convert to radians
angle = vtkMath::RadiansFromDegrees( angle );
// make a normalized quaternion
double w = cos(0.5*angle);
double f = sin(0.5*angle)/sqrt(x*x+y*y+z*z);
x *= f;
y *= f;
z *= f;
// convert the quaternion to a matrix
double matrix[4][4];
vtkMatrix4x4::Identity(*matrix);
double ww = w*w;
double wx = w*x;
double wy = w*y;
double wz = w*z;
double xx = x*x;
double yy = y*y;
double zz = z*z;
double xy = x*y;
double xz = x*z;
double yz = y*z;
double s = ww - xx - yy - zz;
matrix[0][0] = xx*2 + s;
matrix[1][0] = (xy + wz)*2;
matrix[2][0] = (xz - wy)*2;
matrix[0][1] = (xy - wz)*2;
matrix[1][1] = yy*2 + s;
matrix[2][1] = (yz + wx)*2;
matrix[0][2] = (xz + wy)*2;
matrix[1][2] = (yz - wx)*2;
matrix[2][2] = zz*2 + s;
this->Concatenate(*matrix);
}
参考资料
1.http://www.cppblog.com/lovedday/archive/2008/01/12/41031.html
2.https://www.cnblogs.com/cg_ghost/archive/2012/04/27/2473347.html
3.http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle