附錄:矩陣轉換
本主題提供 2D 圖形矩陣轉換的數學概觀。 不過,您不需要知道矩陣數學,才能在 Direct2D 中使用轉換。 如果您對數學感興趣,請閱讀本主題;否則,請放心略過本主題。
矩陣簡介
矩陣是實數的矩形陣列。 矩陣 的順序 是資料列和資料行的數目。 例如,如果矩陣有 3 個數據列和 2 個數據行,則順序為 3 × 2。 矩陣通常會以方括弧括住的矩陣元素來顯示:
標記法:矩陣是由大寫字母所指定。 元素會以小寫字母指定。 下標表示元素的資料列和資料行編號。 例如,ij 是位於矩陣 A 之 i'th 列和 j'th 資料行的專案。
下圖顯示 i × j 矩陣,其中包含矩陣中每個儲存格中的個別元素。
矩陣作業
本節說明在矩陣上定義的基本作業。
加法。 兩個矩陣的總和 A + B 是藉由新增 A 和 B 的對應元素來取得:
- A + B = \[ a*ij* \] + \[ b*ij* \] = \[ a*ij* + b*ij* \]
純量乘法。 此作業會將矩陣乘以實數。 假設有實數 k,則純量產品 kA 會藉由將 A 的每個元素乘以 k來取得。
- kA = k\[ a*ij* \] = \[ k × a*ij* \]
矩陣乘法。 假設有兩個矩陣 A 和 B 具有 order (m × n) 和 (n × p) ,則產品 C = A × B 是具有訂單 (m × p) 的矩陣,定義如下:
或,同樣地:
- c*ij* = a*i*1 x b1*j* + a*i*2 x b2*j* + ... + a*in* + b*nj*
也就是說,若要計算每個元素 cij,請執行下列動作:
- 採用 A 的第 i 列和 B 的第 j 個數據行。
- 將列和資料行中的每個元素配對相乘:第一個資料列專案乘以第一個資料行專案、第二個數據列專案乘以第二個數據行專案等等。
- 加總結果。
以下是將 (2 × 2) 矩陣乘以 (2 × 3) 矩陣的範例。
矩陣乘法不是交換的。 也就是說,A × B ≠ B × A。此外,從定義中,其後面不會乘以每一組矩陣。 左側矩陣中的資料行數目必須等於右側矩陣中的資料列數目。 否則,不會定義×運算子。
識別矩陣。 指定 I 的識別矩陣是定義如下的平方矩陣:
- I*ij* = 1 如果 *i* = *j*,則為 0,否則為 0。
換句話說,識別矩陣會針對每個元素包含 1 個,其中資料列編號等於資料行編號,而所有其他元素則為零。 例如,以下是 3 個× 3 個識別矩陣。
任何矩陣 M 的下列相等保留。
- M x I = M I x M = M
Affine Transforms
相依轉換是一種數學運算,可將一個座標空間對應到另一個座標空間。 換句話說,它會將一組點對應到另一組點。 Affine 轉換有一些功能,讓它們在電腦圖形中很有用。
- Affine 轉換會保留 共構性。 如果三個或多個點落在一行上,它們仍會在轉換之後形成一行。 直線維持直線。
- 兩個相依轉換的組成是一個相依轉換。
2D 空間的 Affine 轉換具有下列形式。
如果您套用稍早指定的矩陣乘法定義,您可以顯示兩個相依轉換的乘積是另一個相依轉換。 若要使用相依轉換來轉換 2D 點,此點會以 1 × 3 矩陣表示。
- P = \|x y 1 \|
前兩個專案包含點的 x 和 y 座標。 1 會放在第三個元素中,讓數學正常運作。 若要套用轉換,請將兩個矩陣相乘,如下所示。
- P' = P × M
這會展開至下列內容。
where
- x' = ax + cy + e y' = bx + dy + f
若要取得轉換點,請取得矩陣 P 的前兩個元素。
- p = (x', y') = (ax + cy + e, bx + dy + f)
注意
1 × n 矩陣稱為 資料列向量。 Direct2D 和 Direct3D 都會使用資料列向量來代表 2D 或 3D 空間中的點。 您可以使用資料行向量 (n × 1) 並轉置轉換矩陣來取得相等的結果。 大部分的圖形文字都會使用資料行向量形式。 本主題提供資料列向量表單,以便與 Direct2D 和 Direct3D 一致性。
接下來的數個區段會衍生基本轉換。
翻譯轉換
轉譯轉換矩陣的格式如下。
將點 P 插入此方程式會產生:
- P' = (*x* + *dx*, *y* + *dy*)
對應至 x、y) X 軸中由 dx 轉譯的 (點,而 Y 軸則 為 dy 。
調整轉換
縮放轉換矩陣的格式如下。
將點 P 插入此方程式會產生:
- P' = (*x* ** * *dx*, *y* * )
對應至 x,y) 以 dx 和 dy縮放的 (點。
繞原點旋轉
在原點周圍旋轉的矩陣具有下列形式。
轉換的點為:
- P' = (*x*cosΘ – ysinΘ、*x*sinΘ + *y*cosΘ)
證明。 若要顯示 P 代表旋轉,請考慮下圖。
假設︰
-
P = (x,y)
-
要轉換的原始點。
-
Φ
-
線條所形成的角度 (0,0) 至 P。
-
Θ
-
旋轉 (x,y) 原點的角度。
-
P' = (x',y')
-
已轉換的點。
-
R
-
行 (0,0) 到 P 的長度。此外,旋轉圓圈的半徑。
注意
此圖表使用幾何中使用的標準座標系統,其中正 y 軸向上指向。 Direct2D 使用 Windows 座標系統,其中正 Y 軸向下點。
X 軸與線條 (0,0) 到 P' 之間的角度為 Ф + Θ。 下列身分識別保留:
- x = R cosФ y = R sinФ x' = R cos (Ф + Θ) y' = R sin (Ф+ Θ)
現在在 Θ 方面解決 x' 和 y'。 透過三角加法公式:
- x' = R (cosФcosΘ – sinФsinΘ) = RcosФcosΘ – RsinФsinΘ y' = R (sinФcosΘ + cosInΘ) = RsinФcosΘ + RcosФsinΘ
替代,我們得到:
- x' = xcosΘ – ysinΘ y' = xsinΘ + ycosΘ
對應至稍早顯示的轉換點 P。
繞任意點旋轉
若要繞著點 (x,y) ,而不是原點旋轉,則會使用下列矩陣。
您可以擷取 (x,y) 成為原點來衍生此矩陣。
讓 (x1、y1) 成為旋轉點 (x0、y0) 繞 (x,y) 點所產生的點。 我們可以衍生 x1,如下所示。
- x1 = (x0 – x) cosΘ – (y0 – y) sinΘ + x1 = x0cosΘ – y0sinΘ + \[ (1 – cosΘ) + ysinΘ \]
現在,使用公式 x1 = ax0 + cy0 + e,將這個方程式插入轉換矩陣中。 使用相同的程式衍生 y1。
扭曲轉換
扭曲轉換是由四個參數所定義:
- Θ:沿著 X 軸扭曲的數量,以 Y 軸的角度測量。
- Ф:沿著 Y 軸扭曲的數量,以 X 軸的角度測量。
- (px、 py) :執行扭曲之點的 x 和 y 座標。
扭曲轉換會使用下列矩陣。
轉換的點為:
- P' = (*x* + *y*tanΘ – *py*tanΘ, *y* + *x*tanФ) – *py*tanФ
或對等:
- P' = (*x* + (*y* – *py*) tanΘ、*y* + (*x* – *px*) tanФ)
若要查看此轉換的運作方式,請個別考慮每個元件。 Θ 參數會以等於 tanΘ 的數量移動 x 方向的每個點。 下圖顯示 Θ 與 X 軸扭曲之間的關聯性。
以下是套用至矩形的相同扭曲:
Ф 參數的效果相同,但沿著 Y 軸:
下圖顯示套用至矩形的 Y 軸扭曲。
最後,參數 px 和 py 會沿著 X 軸和 y 軸移動扭曲的中心點。
代表 Direct2D 中的轉換
所有 Direct2D 轉換都是相依轉換。 Direct2D 不支援非相依轉換。 轉換是由 D2D1_MATRIX_3X2_F 結構表示。 這個結構會定義 3 × 2 矩陣。 因為 affine 轉換的第三個數據行一律是相同的 ([0, 0, 1]) ,而且因為 Direct2D 不支援非相依轉換,所以不需要指定整個 3 × 3 矩陣。 在內部,Direct2D 會使用 3 × 3 個矩陣來計算轉換。
D2D1_MATRIX_3X2_F的成員會根據其索引位置命名:_11成員是元素 (1,1) ,_12成員是元素 (1,2) 等等。 雖然您可以直接初始化結構成員,但建議您使用 D2D1::Matrix3x2F 類別。 這個類別會繼承 D2D1_MATRIX_3X2_F ,並提供協助程式方法來建立任何基本相依轉換。 類別也會定義 operator* () 來撰寫兩個或多個轉換,如 在 Direct2D 中套用轉換中所述。
下一個