(JAVA)计算机图形学与矩阵
平移
旋转
变比
一)矩阵
1)矩阵的乘法运算
矩阵是计算机图形学的重要工具.
计算机图形学要常常用到 矩阵乘法(矩阵与矩阵相乘).
矩阵(Aij)m*n 与矩阵(Bij)n*p 的积为
(Cij)m*p
其中Cij=∑AjkBkj
例: [A11 A12] [B11 B12 ]
[A21 A22] * [B21 B22 ] =
[ A11*B11+ A12*B21 A11*B12+
A12*B22 ]
[ A21*B11+ A22*B21 A21*B12+
A22*B22 ]
显然,后一矩阵的行数必须与前一矩阵的列数相同,否则矩阵乘法没有意义.
矩阵乘法满足结合律,但不满足交换律.
2)基矩阵
数学教科书在讲述向量的坐标表示时,都使用单位向量的概念.
设空间直角坐标系中,i、j 、k
分别为平行于X、Y、Z轴的单位向量,它的坐标表示分别为:
i:(1 ,0,0)
j:(0 ,1,0)
k:(0 ,0,1)
如果把写成一个矩阵,就是:
[1 0 0 ]
[0 1 0 ]
[0 0 1 ]
上面这个矩阵称为单位矩阵或基矩阵。
在以后可以看到,为了统一图形变换的矩阵,一般总是将n维空间的矩阵写成(n+1)的方阵。
这样二维空间的基矩阵就成为:
[1 0 0 ]
[0 1 0 ]
[0 0 1 ]
三维空间的基矩阵为:
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
二)二维图形的基本变换与矩阵表示
1)三种基本变换
1.1)平移(Translate)
平移,是将对象从一位置称动到另一个位置。
要将坐标为(X,Y)的a点,
移动到另一处,若移动的向量为(Tx,Ty),
则,移动后的坐标应为: (X+Tx, Y+Ty)
这种平移变换,可以构造为矩阵的乘法运算:
[1 0 0]
[X Y 1]*[0 1 0]
[Tx Ty 1]
计算结果为:
[ X*1+Y*0+1*Tx X*0+Y*1+1*Ty 1]
=[ 0 0
0]
[
0 0
0]
= [ X+Tx Y+Ty 1 ]
其中“X+Tx”与“Y+Ty”就是平移后a’点的坐标。
1.2)旋转(Rotation)
旋转是以某个参考点为圆心,将对象上的各点围绕圆心转动一定的角度。
1.2.1)已知一个起点位于原点的向量(X,Y),其与X轴的夹角为A,求绕原点旋转角度B后的(X1,Y1):
X=|R|*cosA (|R|为向量的模) (1)
Y=|R|*sinA (2)
X1=|R|*cos(A+B)=|R|*(cosAcosB-sinAsinB) (3)
Y1=|R|*sin(A+B)=|R|*(sinAcosB+cosAsinB) (4)
将(1),(2)代入(3)(4),化简后得:
X1=X*cosB-Y*sinB (5)
Y1=X*sinB+Y*cosB (6)
(5)(6)是一个常用公式.可以用矩阵乘法表示:
[ cos sin ]
[X Y]*[-sin cos ]= [X1 Y1]
这是一个2*2的矩阵, 不能与3*3的平移矩阵进行乘法运算, 为此,我们将其构造成3*3的矩阵:
[ cosB sinB 0
]
[ X Y 1 ] *
[-sinB cosB 0
]
[ 0 0
1 ]
= [X*cosB–Y*sinB X*sinB+Y*cosB 1]
1.2.2)上述的旋转,只限于绕原点的旋转.如要绕不是原点的任意点, 例如坐标为(X0,Y0)的点旋转,
需要先平移图形,平移的向量为-(X0,Y0)。完成旋转变换后,再平移复位。
绕原点旋转的例子见“MyLine”;
绕任一点旋转的例子见“MyLine1”
1.3)变比(Scaling)
是将对象按比例因子放大或缩小的变换。
计算公式:
X’ = X * Sx
Y’ = Y * Sy
其中Sx,Sy称比例因子。S > 1时,放大;0
< S〈 1时缩小。
当S < 0
时,不但会缩放,还会出现出“反射”变换:
如:Sx = -1, Sy = 1 则图形按X轴反射;
Sx = 1, Sy = -1 则图形按Y轴反射;
Sx = -1, Sy = -1 则图形按Y轴反射;
变比变换可以用矩阵表示为:
[ Sx 0
0 ]
[ X Y 1 ] *[ 0 Yz
0
]
[ 0 0
1 ]
= [X*Sx Y*Sy 1]
变比不但会使图形缩放,还会引起图形的移动,若要使图形在发生缩放变形时,某一点的位固定不变(简称定点变比),同样需要在变比变换前进行平移。详见“MyTrangle”.
注:
以上我们将点的坐标写成行的形式,
实际上也可成列的形式(当然,矩阵也要作相应的行列转换).例如,1.1)的平移变换可写成:
[X] [1 0 Tx]
[Y] *[0 1 Ty]
[1] [0 0 1]
(JAVA中定义一些用于二维变换的类,它们就采用了列的形式,参见JAVA
API的“AffineTransform”类的说明。)
2)级联变换与级联矩阵
一个复杂的变换,需要连续进行若干个基本变换才能完成。如前述的围绕任意点旋转,就要通过三个基本变换(平称、旋转、平移)才能完成。这些连续变换序列称为级联变换。
如果我们把组成级联变换的各个基本变换都用矩阵表示,并对这些矩阵进行有序的乘法运算(注意:矩阵不满足交换率),最终化简为一个矩阵(这个矩阵称级联矩阵),这将大大简化图形变换的计算工作,且花费的时间将大大缩短。
可以设想一下,一个由M个点组成的图形(复杂的图形,M将是巨大的),若要进行n个连续的基本变换,就需要进行M * n
次运算;但若运用矩阵,只要进行非常有限的矩阵乘法运算,即可得到一个级联矩阵,图形的每一个点,只要与这个级联矩阵相乘一次,就可以完成图形的复杂变换,效率大为提高。
还可以从编程的角度体会矩阵的神奇:
1)
一个显示三维几何图形各种变换(有关三维图形变换的矩阵,将在下面介绍)的程序,只要维护两组基本数据,一组是组成图形的各点的原始坐标(一般用数组),一组是仅有16个元素的级联矩阵(且最后一列大多情况下多为0)。前者始终不变,后者根据需要不断更新,要显示变换的图形时,只须将存贮各点原始坐标的数组COPY到另一个数组,并与级联矩阵相乘,即可得到变换的图形。
2)可以创建一个包含基本变换的矩阵类,减化工作量.
下面三维图形的基本变换的矩阵表示,可以看作是二维图形基本变换矩阵的推广,证明略去。
(原来的点坐标为X0,Y0,Z0;
变换后的点的坐标为X1,Y1,Z1。
1)平移:
[X1 Y1 X1 1 ]
=
[ 1 0 0 0 ]
= [X0 Y0 Z0 1 ] * [
0 1 0 0 ]
[ 0 0 1
0 ]
[ Tx Ty Tz 1 ]
2)旋转
(以下均为顺时针旋转,若将sin 与 –sin 互换位置,则为反时针旋转
实际上反时针旋转的矩阵就是顺时针旋转矩阵的转置(Transposition, 行与列互换):
The transpose of M (denoted MT
): MTij =
Mji
)
2.1)绕Z轴旋转:
[X1 Y1 X1 1 ]=
[ con sin 0 0
]
=[X0 Y0 Z0 1 ]* [-sin
cos 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
2.2)绕X轴旋转:
[X1 Y1 X1 1 ]=
[ 1 0
0 0 ]
= [X0 Y0 Z0 1 ] *[
0 con sin 0 ]
[ 0 –sin cos
0 ]
[ 0 0 0
1 ]
2.3)绕Y轴旋转:
[X1 Y1 X1 1 ]=
[ cos 0 -sin
0 ]
= [X0 Y0 Z0 1 ]* [ 0
1 0 0 ]
[ sin 0 cos
0 ]
[ 0
0 0 1 ]
3)变比:
[X1 Y1 X1 1 ]
=
[ Sx 0
0 0 ]
= [X0 Y0 Z0 1 ] * [ 0
Sy 0 0 ]
[ 0 0 Sz 0 ]
[ 0 0 0 1 ]
四)绕任意轴旋转
一)旋转轴通过原点
1)先将过原点的旋转轴向量化为一个单位向量(a,b,c)。
例如,一个过原点的向量为(X0,Y0,Z0),向量的长为|R|,则:
a = X0/|R|,
b = Y0/|R|,
c = Z0/|R|,
2)分两步把旋转轴变换到z轴上去(与Z轴重合): 1)将旋转轴变换到yoz平面上,2)
将yoz平面上的旋转轴变换到z轴上。详述如下:
2.1)将旋转轴变换到yoz平面上
上图是沿着z轴方向看去示意图(视线与yox平面垂直,与xoz
、yoz平面平行)。可以看出,将旋转轴变换到yoz平面上,是一个绕z轴旋转的变换,
容易推出:
cosA = b /d
sinA = a /d
式中d是轴向量在xoy面的投影长:d = sqrt(a^2 + b^2)
于是可以用矩阵表示为:
[b/d a/d 0 0]
[-a/d b/d
0 0]
[0 0 1 0]
[0 0 0 1]
逆变换矩阵为(为上述矩阵的转置):
[b/d -a/d
0 0]
[a/d
b/d 0 0]
[0 0 1 0]
[0 0 0 1]
2.2) 将yoz平面上的旋转轴变到z轴上。
上图是完成第一步旋转后、沿着x轴方向看去示意图(视线与yoz平面垂直,与yox、xoz平面平行),
可以看出,将旋转轴变换到z轴上(与Z轴重合),是一个绕X轴旋转的变换.
容易推出:
cosB = c / 1 = c
sinB = d / 1 =d
于是可用矩阵表示为:
[1 0 0 0]
[0 c d 0]
[0 -d
c 0]
[0 0 0 1]
相应逆变换矩阵:
[1 0 0 0]
[0 c -d
0]
[0 d c 0]
[0 0 0 1]
归纳一下,我们对于空间任意点围绕某个任意方向且过原点的轴旋转的变换矩阵就是:
[
b/d a/d 0 0] [1 0 0 0]
[-a/d b/d 0 0] [0 c d 0] M =
[0 0 1 0] x [0
-d c 0] x
[0 0 0 1] [0
0 0 1]
[cosA sinA 0
0] [1 0 0 0] [b/d -a/d
0 0]
[-sinA cosA 0 0] [0 c
–d 0] [a/d b/d 0 0]
[0 0 1 0] x [0
d c 0] x
[0 0 1 0]
[0 0 0
1] [0 0 0 1] [0 0 0 1]
前两个实现任意轴与Z轴的重合,第三个是绕Z轴旋,第四、第五分别是第二、第一的逆过程。
二)旋转轴不通过原点
前面分析的是旋转轴过原点的情况,对于不过原点的旋转轴,只需在M的左右两边各加上一个平移变换即可。这个平移变换的元素是根据轴向量与原点之间的距离向量得到的,比如旋转轴与原点的距离向量是(lx,
ly, lz),则我们的变换就变成
[1 0 0 0] [1 0 0 0]
[0 1 0 0] [0 1 0 0]
m = [0 0 1 0] x M x [0 0 1 0]
[-lx -ly -lz
1] [lx ly lz 1]