1 简介

计算机图形学中的应用非常广泛的变换是一种称为仿射变换的特殊变换,在仿射变换中的基本变换包括平移、旋转、缩放、剪切这几种。本文以及接下来的几篇文章重点介绍一下关于旋转的变换,包括二维旋转变换、三维旋转变换以及它的一些表达方式(旋转矩阵、四元数、欧拉角等)。

2 绕原点二维旋转

首先要明确旋转在二维中是绕着某一个点进行旋转,三维中是绕着某一个轴进行旋转。二维旋转中最简单的场景是绕着坐标原点进行的旋转,如下图所示:

如图所示点v 绕 原点旋转θ 角,得到点v’,假设 v点的坐标是(x, y) ,那么可以推导得到 v’点的坐标(x’, y’)(设原点到v的距离是r,原点到v点的向量与x轴的夹角是ϕ )
x=rcosϕ
y=rsinϕ
x′=rcos(θ+ϕ)
y′=rsin(θ+ϕ)
通过三角函数展开得到
x′=rcosθcosϕ−rsinθsinϕ
y′=rsinθcosϕ+rcosθsinϕ
带入x和y表达式得到
x′=xcosθ−ysinθ
y′=xsinθ+ycosθ
写成矩阵的形式是:
[cos⁡(θ)−sin⁡(θ)sin⁡(θ)cos⁡(θ)]\begin{bmatrix} \cos(\theta)&-\sin(\theta)\\ \sin(\theta)&\cos(\theta) \end{bmatrix} [cos(θ)sin(θ)​−sin(θ)cos(θ)​]

尽管图示中仅仅表示的是旋转一个锐角θ的情形,但是我们推导中使用的是三角函数的基本定义来计算坐标的,因此当旋转的角度是任意角度(例如大于180度,导致v’点进入到第四象限)结论仍然是成立的。

3 绕任意点的二维旋转

绕原点的旋转是二维旋转最基本的情况,当我们需要进行绕任意点旋转时,我们可以把这种情况转换到绕原点的旋转,思路如下:

  1. 首先将旋转点移动到原点处
  2. 执行如2所描述的绕原点的旋转
  3. 再将旋转点移回到原来的位置

也就是说在处理绕任意点旋转的情况下需要执行两次平移的操作。假设平移的矩阵是T(x,y),也就是说我们需要得到的坐标 v’=T(x,y)RT(-x,-y)(我们使用的是列坐标描述点的坐标,因此是左乘,首先执行T(-x,-y))

在计算机图形学中,为了统一将平移、旋转、缩放等用矩阵表示,需要引入齐次坐标。(假设使用2x2的矩阵,是没有办法描述平移操作的,只有引入3x3矩阵形式,才能统一描述二维中的平移、旋转、缩放操作。同理必须使用4x4的矩阵才能统一描述三维的变换)。

对于二维平移,如下图所示,P点经过x和y方向的平移到P’点,可以得到:
{x′=x+txy′=y+ty\left\{\begin{aligned}x^\prime=x+t_x\\ y^\prime=y+t_y\end{aligned}\right. {x′=x+tx​y′=y+ty​​

由于引入了齐次坐标,在描述二维坐标的时候,使用(x,y,w)的方式(一般w=1),于是可以写成下面矩阵的形式
[x′y′1]=[10tx01ty001]⋅[xy1]\begin{bmatrix} x^\prime\\ y^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} 1&0&t_x\\ 0&1&t_y\\ 0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ⎣⎡​x′y′1​⎦⎤​=⎣⎡​100​010​tx​ty​1​⎦⎤​⋅⎣⎡​xy1​⎦⎤​

按矩阵乘法展开,正好得到上面的表达式。也就是说平移矩阵是
[10tx01ty001]\begin{bmatrix} 1&0&t_x\\ 0&1&t_y\\ 0&0&1 \end{bmatrix}⎣⎡​100​010​tx​ty​1​⎦⎤​

如果平移值是 (−tx,−ty)(-t_x,-t_y)(−tx​,−ty​) 那么很明显平移矩阵式
[10−tx01−ty001]\begin{bmatrix} 1&0&-t_x\\ 0&1&-t_y\\ 0&0&1 \end{bmatrix}⎣⎡​100​010​−tx​−ty​1​⎦⎤​

我们可以把2中描述的旋转矩阵也扩展到3x3的方式,变为:
[x′y′1]=[cos⁡(θ)−sin⁡(θ)0sin⁡(θ)cos⁡(θ)0001]⋅[xy1]\begin{bmatrix} x^\prime\\ y^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} \cos(\theta)&-\sin(\theta)&0\\ \sin(\theta)&\cos(\theta)&0\\ 0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ⎣⎡​x′y′1​⎦⎤​=⎣⎡​cos(θ)sin(θ)0​−sin(θ)cos(θ)0​001​⎦⎤​⋅⎣⎡​xy1​⎦⎤​

从平移和旋转的矩阵可以看出,3x3矩阵的前2x2部分是和旋转相关的,第三列与平移相关。有了上面的基础之后,我们很容易得出二维中绕任意点旋转的旋转矩阵了,只需要把三个矩阵乘起来即可:
[x′y′1]=[10tx01ty001]⋅[cos⁡(θ)−sin⁡(θ)0sin⁡(θ)cos⁡(θ)0001]⋅[10−tx01−ty001]⋅[xy1]\begin{bmatrix} x^\prime\\ y^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} 1&0&t_x\\ 0&1&t_y\\ 0&0&1 \end{bmatrix}\cdot \begin{bmatrix} \cos(\theta)&-\sin(\theta)&0\\ \sin(\theta)&\cos(\theta)&0\\ 0&0&1 \end{bmatrix}\cdot \begin{bmatrix} 1&0&-t_x\\ 0&1&-t_y\\ 0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ⎣⎡​x′y′1​⎦⎤​=⎣⎡​100​010​tx​ty​1​⎦⎤​⋅⎣⎡​cos(θ)sin(θ)0​−sin(θ)cos(θ)0​001​⎦⎤​⋅⎣⎡​100​010​−tx​−ty​1​⎦⎤​⋅⎣⎡​xy1​⎦⎤​

4 三维基本旋转

我们可以把一个旋转转换为绕基本坐标轴的旋转,因此有必要讨论一下绕三个坐标值x、y、z的旋转。
本文在讨论过程中使用的是类似于OpenGL中定义的右手坐标系,同时旋转角度的正负也遵循右手坐标系的约定。如下图所示

4.1 绕X轴的旋转

在三维场景中,当一个点P(x,y,z)绕x轴旋转θ角得到点P’(x’,y’,z’)。由于是绕x轴进行的旋转,因此x坐标保持不变,y和z组成的yoz(o是坐标原点)平面上进行的是一个二维的旋转,可以参考上图(y轴类似于二维旋转中的x轴,z轴类似于二维旋转中的y轴),于是有:
x′=x
y′=ycosθ−zsinθ
z′=ysinθ+zcosθ
写成(4x4)矩阵的形式
[x′y′z′1]=[10000cos⁡(θ)−sin⁡(θ)00sin⁡(θ)cos⁡(θ)00001]⋅[xyz1]\begin{bmatrix} x^\prime\\ y^\prime\\ z^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} 1&0&0&0\\ 0&\cos(\theta)&-\sin(\theta)&0\\ 0&\sin(\theta)&\cos(\theta)&0\\ 0&0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} ⎣⎢⎢⎡​x′y′z′1​⎦⎥⎥⎤​=⎣⎢⎢⎡​1000​0cos(θ)sin(θ)0​0−sin(θ)cos(θ)0​0001​⎦⎥⎥⎤​⋅⎣⎢⎢⎡​xyz1​⎦⎥⎥⎤​

4.2 绕Y轴旋转

绕Y轴的旋转和绕X轴的旋转类似,Y坐标保持不变,除Y轴之外,ZOX组成的平面进行一次二维的旋转(Z轴类似于二维旋转的X轴,X轴类似于二维旋转中的Y轴,注意这里是ZOX,而不是XOZ,观察上图中右手系的图片可以很容易了解到这一点),同样有:
x′=zsinθ+xcosθ
y′=y
z′=zcosθ−xsinθ
写成(4x4)矩阵的形式
[x′y′z′1]=[cos⁡(θ)0sin⁡(θ)00100−sin⁡(θ)0cos⁡(θ)00001]⋅[xyz1]\begin{bmatrix} x^\prime\\ y^\prime\\ z^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} \cos(\theta)&0&\sin(\theta)&0\\ 0&1&0&0\\ -\sin(\theta)&0&\cos(\theta)&0\\ 0&0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} ⎣⎢⎢⎡​x′y′z′1​⎦⎥⎥⎤​=⎣⎢⎢⎡​cos(θ)0−sin(θ)0​0100​sin(θ)0cos(θ)0​0001​⎦⎥⎥⎤​⋅⎣⎢⎢⎡​xyz1​⎦⎥⎥⎤​

4.3 绕Z轴旋转

与上面类似,绕Z轴旋转,Z坐标保持不变,xoy组成的平面内正好进行一次二维旋转(和上面讨论二维旋转的情况完全一样)
[x′y′z′1]=[cos⁡(θ)−sin⁡(θ)00sin⁡(θ)cos⁡(θ)0000100001]⋅[xyz1]\begin{bmatrix} x^\prime\\ y^\prime\\ z^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} \cos(\theta)&-\sin(\theta)&0&0\\ \sin(\theta)&\cos(\theta)&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} ⎣⎢⎢⎡​x′y′z′1​⎦⎥⎥⎤​=⎣⎢⎢⎡​cos(θ)sin(θ)00​−sin(θ)cos(θ)00​0010​0001​⎦⎥⎥⎤​⋅⎣⎢⎢⎡​xyz1​⎦⎥⎥⎤​

4.4 小结

上面描述了三维变换中绕单一轴旋转的矩阵表达形式,绕三个轴旋转的矩阵很类似,其中绕y轴旋转的矩阵与绕x和z轴旋转的矩阵略有点不同(主要是三个轴向顺序和书写矩阵的方式不一致导致的,绕三个不同坐标旋转轴以及其他二个坐标轴组成平面的顺序是: XYZ(绕x轴) YZX(绕y轴) ZXY(绕z轴),其中绕y轴旋转,其他两个轴是ZX,这和我们书写矩阵按
[x′y′z′1]\begin{bmatrix} x^\prime\\ y^\prime\\ z^\prime\\ 1 \end{bmatrix} ⎣⎢⎢⎡​x′y′z′1​⎦⎥⎥⎤​

的方式不一致,而导致看起来绕Y轴旋转的矩阵似乎是和其他两个矩阵不一致。如果我们颠倒写法,将公式写成
[z′y′x′1]=[cos⁡(θ)0−sin⁡(θ)00100sin⁡(θ)0cos⁡(θ)00001]⋅[xyz1]\begin{bmatrix} z^\prime\\ y^\prime\\ x^\prime\\ 1 \end{bmatrix}= \begin{bmatrix} \cos(\theta)&0&-\sin(\theta)&0\\ 0&1&0&0\\ \sin(\theta)&0&\cos(\theta)&0\\ 0&0&0&1 \end{bmatrix}\cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} ⎣⎢⎢⎡​z′y′x′1​⎦⎥⎥⎤​=⎣⎢⎢⎡​cos(θ)0sin(θ)0​0100​−sin(θ)0cos(θ)0​0001​⎦⎥⎥⎤​⋅⎣⎢⎢⎡​xyz1​⎦⎥⎥⎤​

的方式,那么这三个旋转矩阵看起来在形式上就统一了,都是
[cos⁡(θ)−sin⁡(θ)sin⁡(θ)cos⁡(θ)]\begin{bmatrix} \cos(\theta)&-\sin(\theta)\\ \sin(\theta)&\cos(\theta) \end{bmatrix} [cos(θ)sin(θ)​−sin(θ)cos(θ)​]

这种表现形式了(左上角都是−sinθ)

5. 绕任意轴的三维旋转

绕任意轴旋转的情况比较复杂,主要分为两种情况,一种是平行于坐标轴的,一种是不平行于坐标轴的。

5.1 平行于坐标轴的

对于平行于坐标轴的,我们首先将旋转轴平移至与坐标轴重合,然后进行旋转,最后再平移回去。

  1. 将旋转轴平移至与坐标轴重合,对应平移操作 T
  2. 旋转,对应操作 R
  3. 步骤1的逆过程,对应操作 T

整个过程就是:P′=P⋅T⋅R⋅T−1P^\prime=P\cdot T\cdot R\cdot T^{-1}P′=P⋅T⋅R⋅T−1

5.1 不平行于坐标轴的
  1. 将旋转轴平移至原点
  2. 将旋转轴旋转至YOZ平面
  3. 将旋转轴旋转至于Z轴重合
  4. 绕Z轴旋转θ度
  5. 执行步骤3的逆过程
  6. 执行步骤2的逆过程
  7. 执行步骤1的逆过程

假设用v1(a1, b2, c2)和v2(a2, b2, c2)来表示旋转轴,θ表示旋转角度。为了方便推导,暂时使用右手系并使用列向量,待得出矩阵后转置一下即可,上面第1、2、3步骤对应的流程图如下:

步骤1是一个平移操作,将v1v2平移至原点,对应的矩阵为:
T(x,y,z)=[100−a1010−b1001−c10001]T(x,y,z)=\begin{bmatrix} 1&0&0&-a_1\\ 0&1&0&-b_1\\ 0&0&1&-c_1\\ 0&0&0&1 \end{bmatrix} T(x,y,z)=⎣⎢⎢⎡​1000​0100​0010​−a1​−b1​−c1​1​⎦⎥⎥⎤​

步骤2是一个旋转操作,将 P 旋转至XOZ平面,步骤3也是一个旋转操作,将p旋转至与Z轴重合,这两个操作对应的图如下:

做点p在平面YOZ上的投影点q。再过q做Z轴垂线,则r是p绕X轴旋转所得,且旋转角度为α,且
cos⁡α=cb2+c2sin⁡α=bb2+c2\cos\alpha=\frac{c}{\sqrt{b^2+c^2}}\quad\sin\alpha=\frac{b}{\sqrt{b^2+c^2}} cosα=b2+c2​c​sinα=b2+c2​b​

于是绕X轴旋转矩阵为:
[10000cb2+c2−bb2+c200bb2+c2cb2+c200001]\begin{bmatrix} 1&0&0&0\\ 0&\frac{c}{\sqrt{b^2+c^2}}&-\frac{b}{\sqrt{b^2+c^2}}&0\\ 0&\frac{b}{\sqrt{b^2+c^2}}&\frac{c}{\sqrt{b^2+c^2}}&0\\ 0&0&0&1 \end{bmatrix}⎣⎢⎢⎡​1000​0b2+c2​c​b2+c2​b​0​0−b2+c2​b​b2+c2​c​0​0001​⎦⎥⎥⎤​

现在将r绕Y轴旋转至与Z轴重合,旋转的角度为 −β-\beta−β(方向为顺时针),且
cos⁡(−β)=cos⁡(β)=b2+c2a2+b2+c2sin⁡(−β)=−sin⁡(β)=−aa2+b2+c2\cos(-\beta)=\cos(\beta)=\frac{\sqrt{b^2+c^2}}{\sqrt{a^2+b^2+c^2}}\quad \sin(-\beta)=-\sin(\beta)=-\frac{a}{\sqrt{a^2+b^2+c^2}}cos(−β)=cos(β)=a2+b2+c2​b2+c2​​sin(−β)=−sin(β)=−a2+b2+c2​a​

绕Z轴旋转矩阵为:
[cos⁡(−β)0sin⁡(−β)00100−sin⁡(−β)0cos⁡(−β)00001]=[b2+c2a2+b2+c20−aa2+b2+c200100aa2+b2+c20b2+c2a2+b2+c200001]\begin{bmatrix} \cos(-\beta)&0&\sin(-\beta)&0\\ 0&1&0&0\\ -\sin(-\beta)&0&\cos(-\beta)&0\\ 0&0&0&1 \end{bmatrix}= \begin{bmatrix} \frac{\sqrt{b^2+c^2}}{\sqrt{a^2+b^2+c^2}}&0&-\frac{a}{\sqrt{a^2+b^2+c^2}}&0\\ 0&1&0&0\\ \frac{a}{\sqrt{a^2+b^2+c^2}}&0&\frac{\sqrt{b^2+c^2}}{\sqrt{a^2+b^2+c^2}}&0\\ 0&0&0&1 \end{bmatrix} ⎣⎢⎢⎡​cos(−β)0−sin(−β)0​0100​sin(−β)0cos(−β)0​0001​⎦⎥⎥⎤​=⎣⎢⎢⎢⎡​a2+b2+c2​b2+c2​​0a2+b2+c2​a​0​0100​−a2+b2+c2​a​0a2+b2+c2​b2+c2​​0​0001​⎦⎥⎥⎥⎤​

最后是绕Z轴旋转,对应的矩阵如下:
[cos⁡(θ)−sin⁡(θ)00sin⁡(θ)cos⁡(θ)0000100001]\begin{bmatrix} \cos(\theta)&-\sin(\theta)&0&0\\ \sin(\theta)&\cos(\theta)&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{bmatrix} ⎣⎢⎢⎡​cos(θ)sin(θ)00​−sin(θ)cos(θ)00​0010​0001​⎦⎥⎥⎤​

如果旋转轴是过原点的,那么第一步和最后一步的平移操作可以省略,也就是把中间五个矩阵连乘起来,再转置一下,得到下面的绕任意轴旋转的矩阵:
M=Rx(−α)⋅Ry(β)⋅Rz(θ)⋅Ry(−β)⋅Rx(α)M=R_x(-\alpha)\cdot R_y(\beta)\cdot R_z(\theta)\cdot R_y(-\beta)\cdot R_x(\alpha) M=Rx​(−α)⋅Ry​(β)⋅Rz​(θ)⋅Ry​(−β)⋅Rx​(α)

即:

参考文献

旋转——绕原点二维旋转,绕任意点的二维旋转,三维基本旋转,绕任意轴的三维旋转相关推荐

  1. matlab控制三角形绕原点旋转任意角度

    项目中遇到一个问题,需要把正三角形绕原点旋转任意角度,平时操作图片的时候,顺便旋转,感觉好像很简单,但是自己去做的时候还是有些困难. 我觉得旋转的难点在于由原始点计算新的目标点上,因为你需要考虑点位于 ...

  2. 【数学】齐次坐标、三维点/向量的平移、缩放、旋转

    [坐标系约定] 约定坐标系是为了在计算过程中需要脑中进行想象的部分有所依据.我们约定轴遵守右手系,如下: 可以认为轴向屏幕右侧,轴向屏幕上,轴向屏幕外. [齐次坐标] 向量与点的齐次坐标是有不同的,若 ...

  3. QR code 二维码基础入门教程(二)

    QR code 二维码基础入门教程(二) 承接上文,让我们继续下面的步骤 纠错码编码 先说说纠错容量 纠错码可以纠正两种错误: 拒读错误(错误码位置已知),是一个没有扫到或者无法译码的符号字符,需要一 ...

  4. 浅析伪罗伯特法所构造的任意阶数伪二次幻方中某一任意位置权值的一般求法

    二次幻方(Magic Square)是一种每行.列和对角线上的数字和都相等的二维数组.构造二次幻方的方法有很多种,其中最著名的是罗伯特法,又称楼梯法,其核心是在奇数阶二次幻方的首行正中列填上1,随后下 ...

  5. HTML5七夕情人节表白网页(流星雨3D旋转相册) HTML+CSS+JS 求婚 html生日快乐祝福代码网页 520情人节告白代码 程序员表白源码 3D旋转相册 js烟花代码

    HTML5七夕情人节表白网页❤流星雨3D旋转相册❤ HTML+CSS+JS 求婚 html生日快乐祝福代码网页 520情人节告白代码 程序员表白源码 3D旋转相册 js烟花代码 css爱心表白 这是程 ...

  6. python使用matplotlib可视化、自定义Y轴轴标签刻度旋转的角度(customize degree rotating axis tick labels in matplotlib)

    python使用matplotlib可视化.自定义Y轴轴标签刻度旋转的角度(customize degree rotating axis tick labels in matplotlib y aix ...

  7. (转)ZXing生成二维码和带logo的二维码,模仿微信生成二维码效果

    场景:移动支付需要对二维码的生成与部署有所了解,掌握目前主流的二维码生成技术. 1 ZXing 生成二维码 首先说下,QRCode是日本人开发的,ZXing是google开发,barcode4j也是老 ...

  8. php 二维数组中去重,PHP实现二维数组去重功能示例

    PHP实现二维数组去重功能示例 发布于 2017-08-07 21:05:17 | 68 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Prep ...

  9. Py之qrcode:调用python的qrcode库两种方式生成二维码、带logo的二维码

    Py之qrcode:调用python的qrcode库两种方式生成二维码.带logo的二维码 目录 python编程实现生成二维码 1.第一种方式-纯文本 2.第二种方式-带logo

最新文章

  1. js 闭包 实战1
  2. javascript编程风格
  3. ML之SVM:SVM算法的简介、应用、经典案例之详细攻略
  4. 使用java多线程分批处理数据工具类
  5. 计算机硬件系统的运行速度,电脑运行速度不给力 需要更换哪些硬件?
  6. 128位java_求一个java算法,用128位密钥的AES加密128位明文,得出的密文还是128位...很着急,非常感谢各位大神,求救!...
  7. from import 导入时找不到module的解决办法(Python模块包中_init_.py文件的作用)
  8. 使用工具分析 SAP UI5 应用前端执行的性能问题
  9. Razor 也可说是一个asp.net模板引擎,用不着学习 T4 了
  10. 华为路由器hilink怎么用_华为无线充电怎么用?MatePadPro无线充电使用方法
  11. 服务器上文件夹没有共享,服务器没有共享文件夹
  12. 一个PHP多个界面跳转,php中的多种界面跳转方式
  13. FA:标准萤火虫算法及Python实现
  14. js实现上传图片之后回显
  15. iOS面试合集,面试看这一篇就够了。
  16. 如何修复硬盘的分区表
  17. 消费升级背景下零食行业发展报告_三只松鼠IPO闯关成功“零食第一股”能否守住食品安全底线...
  18. 2017南宁(重温经典)
  19. 传奇开区网站如何添加流量统计代码
  20. 菲姐游泳(python)

热门文章

  1. matlab米氏方程作图,双倒数作图法米氏方程
  2. 007 UseGCLogFileRotation NumberOfGCLogFiles GCLogFileSize
  3. 区块链中的“余额宝”
  4. [附源码]SSM计算机毕业设计鞋店销售管理JAVA
  5. 模糊理论在机器人传感器中的应用_超声波传感器和激光雷达传感器在机器人避障中的应用...
  6. mac本用WTG(Windows To Go)安装Win10到移动硬盘
  7. 输电杆塔导线地线比载计算,应力计算
  8. 杰里之TWS实际连接流程【篇】
  9. 少侠,你的transducer到了,请拿去装逼~
  10. 403-In general, this can occur when there is a genuine Cross Site Request Forgery, or whe