首先review一下矩陣的基礎知識:
m×n 矩陣是排列在 m 行和 n 列中的一系列數(shù)泽篮。下圖顯示幾個矩陣普气。
可以通過將單個元素相加來加合兩個尺寸相同的矩陣谜疤。下圖顯示了兩個矩陣相加的示例。
m×n 矩陣可與一個 n×p 矩陣相乘现诀,結果為一個 m×p 矩陣夷磕。第一個矩陣的列數(shù)必須與第二個矩陣的行數(shù)相同。例如仔沿,一個 4×2 矩陣與一個 2×3 矩陣相乘坐桩,產(chǎn)生一個 4×3 矩陣。
矩陣的行列的平面點可視為矢量封锉。例如绵跷,(2, 5) 是具有兩個組件的矢量,(3, 7, 1) 是具有三個組件的矢量成福。兩個矢量的點積定義如下:
(a, b) ? (c, d) = ac + bd
(a, b, c) ? (d, e, f) = ad + be + cf
例如碾局,(2, 3) 和 (5, 4) 的點積是 (2)(5) + (3)(4) = 22。(2, 5, 1) 和 (4, 3, 1) 的點積是 (2)(4) + (5)(3) + (1)(1) = 24奴艾。請注意净当,兩個矢量的點積是數(shù)字,而不是另一個矢量蕴潦。另外請注意像啼,只有當兩個矢量的組件數(shù)相同時,才能計算點積潭苞。
將 A(i, j) 作為矩陣 A 中第 i 行忽冻、第 j 列的項。例如此疹,A(3, 2)是矩陣 A 中第 3 行甚颂、第 2 列的項。假定 A秀菱、B 和 C 是矩陣振诬,且 AB = C,則 C 的項計算如下:
C(i, j) =(A 的第 i 行)?(B 的第 j 列)
下圖顯示了矩陣相乘的幾個示例衍菱。
以第二個等式為例赶么,假設等式兩邊的矩陣分別是a、b脊串、c辫呻,1 * 3的矩陣和3 * 2的矩陣相乘清钥,得到的結果為1 * 2的矩陣。
其中c[0][0] = a[0][0] * b[0][0]+a[0][1] * b[1][0]+a[0][2] * b[2][0]放闺,c[0][1]=a[0][0] * b[0][1]+a[0][1] * b[1][1]+a[0][2] * b[2][1]祟昭。
矩陣的加法、乘法怖侦,可以用來做坐標轉換篡悟。我們通常使用3 * 3(如果不需要旋轉,則2*2的矩陣即可)的矩陣來做平面上的各種坐標轉換匾寝,包括x/y軸的平移搬葬、旋轉。現(xiàn)在來看一個簡單的坐標系轉換的例子:假設我們的客戶區(qū)分辨率是100 * 100艳悔,要在客戶區(qū)中心點畫一個點急凰,這個點的坐標是(x, y)。現(xiàn)在如果我們調整了客戶區(qū)分辨率為400 * 300猜年,此時如果還需要保持這個點的相對位置不變抡锈,計算他的坐標應該是(x * 400 / 100, y * 300 / 100)。這個計算過程很簡單乔外,那么用矩陣操作應該如何來實現(xiàn)呢企孩?
我們將這個點視為一個1 * 2的矩陣,將其乘以一個2 * 2的矩陣袁稽,得出的仍然是一個1 * 2的矩陣勿璃,就是新的坐標了。由于屏幕分辨率在x推汽、y軸分別擴大為原來的4倍和3倍补疑,那么我們只要將點的x、y軸坐標都擴大到原來的4歹撒、3倍即可莲组。公式如下:
等式左邊的第二個矩陣,就是用來實現(xiàn)坐標轉換的矩陣暖夭。其中b[0][0]就是x軸的擴大倍數(shù)锹杈,b[1][1]就是在y軸上的擴大倍數(shù)。這里面b[0][1]和b[1][0]永遠是0迈着。坐標系的這種轉換竭望,叫做線性變換。
OK裕菠∫澹看完這個例子,是不是覺得用矩陣比直接計算還麻煩?嗯旧烧,對于這種簡單的情況是這樣的影钉。不過別急,繼續(xù)看坐標系旋轉的情況掘剪,如果現(xiàn)在要求這個客戶區(qū)逆時針旋轉30度平委,要保持這個點的相對位置不變,他的新坐標應該是多少呢夺谁?
普通的計算的公式就不陳述了廉赔,這就是個初中幾何題目。我們直接來看怎樣通過矩陣操作實現(xiàn)予权。首先看公式:在二維空間中,旋轉可以用一個單一的角 θ 定義浪册。作為約定扫腺,正角表示逆時針旋轉。關于原點逆時針旋轉 θ 的矩陣是:
也就是說村象,逆時針旋轉30度的新坐標就是:
當然笆环,除此之外,坐標系還有平移厚者,但是這個就簡單了躁劣,只是一個簡單的矩陣加法。比如(x, y)向右平移一個單位库菲,用矩陣就是[x, y] + [1, 0]就是是(x + 1, y)账忘。
下圖顯示了應用于點 (2, 1) 的幾個變換:
前圖中顯示的所有變換都是線性變換。某些其他變換(如平移)不是線性的熙宇,不能表示為與 2×2 矩陣相乘的形式鳖擒。假定您要從點 (2, 1) 開始,將其旋轉 90 度烫止,在 x 方向將其平移 3 個單位蒋荚,在 y 方向將其平移 4 個單位」萑洌可通過先使用矩陣乘法再使用矩陣加法來完成此操作期升。
后面跟一平移(與 1×2 矩陣相加)的線性變換(與 2×2 矩陣相乘)稱為仿射變換,如上圖所示互躬。放射變換(先乘后加)可以通過乘以一個3*3的矩陣來實現(xiàn)播赁,若要使其起作用,平面上的點必須存儲于具有虛擬第三坐標的 1×3 矩陣中吼渡。通常的方法是使所有的第三坐標等于 1行拢。例如,矩陣 [2 1 1] 代表點 (2, 1)。下圖演示了表示為與單個 3×3 矩陣相乘的仿射變換(旋轉 90 度舟奠;在 x 方向上平移 3 個單位竭缝,在 y 方向上平移 4 個單位):
在前面的示例中,點 (2, 1) 映射到了點 (2, 6)沼瘫。請注意抬纸,3×3 矩陣的第三列包含數(shù)字 0,0耿戚,1湿故。對于仿射變換的 3×3 矩陣而言,情況將總是如此膜蛔。重要的數(shù)字是列 1 和列 2 中的 6 個數(shù)字坛猪。矩陣左上角的 2×2 部分表示變換的線性部分,第 3 行中的前兩項表示平移皂股。
在使用3 * 3的矩陣做仿射變換時候墅茉,表示點的矩陣變成了一個1 * 3矩陣,這個矩陣中的最后一個值(a[0][2])必須設置成1呜呐。對于3 * 3矩陣b就斤,其最后一列的值是多少是沒有關系的,因為他們不會影響結果中的前兩列蘑辑。不過如上洋机,經(jīng)常將他們設置為0,0洋魂,1绷旗。這一列對于坐標轉換的結果并沒有任何影響,但是他們是必須的副砍,因為矩陣相乘必須滿足開篇所講的“相乘的兩個矩陣第一個矩陣的列數(shù)必須與第二個矩陣的行數(shù)相同”刁标。
矩陣類“Matrix”
在.Net Framework中,又一個矩陣類“Matrix”址晕。其內置了點坐標轉換(TransformPoints)膀懈、平移(Translate)、縮放(Scale)谨垃、旋轉(Rotate)方法启搂。下面的示例創(chuàng)建了復合變換(先旋轉 30 度,再在 y 方向上縮放 2 倍刘陶,然后在 x 方向平移 5 個單位)的矩陣:
Matrix myMatrix = newMatrix();
myMatrix.Rotate(30);
myMatrix.Scale(1, 2, MatrixOrder.Append);
myMatrix.Translate(5, 0, MatrixOrder.Append);
除了Matrix類以外胳赌,.Net Framework中也有其他用于坐標系轉換的類,比如System.Drawing.Graphics匙隔。具體用法請查閱相關文檔疑苫。
以上只是利用矩陣進行平面坐標系轉換的方法。如果是三位坐標系,也是可以利用矩陣來操作的捍掺,但Matrix類不行撼短,因為其本身的定位就是“封裝表示幾何變換的 3 x 3 仿射矩陣”。
附上幾個三維空間的旋轉公式:
上面是分別繞單個軸旋轉的公式挺勿。復雜的旋轉可以通過這三個公式組合而成曲横,任何 3 維旋轉矩陣都可以用這三個角 θx, θy, 和 θz 來刻畫,并且可以表示為 roll, pitch 和 yaw 矩陣的乘積不瓶。