為何轉換順序很重要
單一的 Matrix 物件可儲存單一轉換或一系列轉換。 後者稱為複合轉換。 複合轉換矩陣的取得方式是乘以個別轉換的矩陣。
複合轉換範例
在複合轉換中,個別轉換的順序非常重要。 例如,如果先旋轉、再縮放,然後平移,則取得的結果會與先平移、再旋轉,然後縮放的結果不同。 在 GDI+ 中,複合轉換是從左到右建置。 假設 S、R 和 T 依次代表縮放、旋轉和轉換矩陣,則 SRT (依此順序) 的結果是先縮放、再旋轉,然後轉換所產生的複合轉換矩陣。 SRT 產生的矩陣和 TRS 產生的矩陣不同。
順序很重要的原因之一是,旋轉和縮放這類的轉換是根據座標系統的原點來進行。 縮放中心位於原點的物件所產生的結果,與縮放已從原點移開的物件不同。 同樣地,旋轉中心位於原點的物件所產生的結果,也會與旋轉已從原點移開的物件不同。
下列範例組合了縮放、旋轉和轉換 (依此順序),形成複合轉換。 傳遞至 RotateTransform 方法的 Append 引數指出旋轉將在縮放之後進行。 同樣地,傳遞至 Append 方法的 TranslateTransform 引數會指出轉換將在旋轉之後進行。 Append 和 Prepend 是 MatrixOrder 列舉的成員。
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.RotateTransform(28, MatrixOrder.Append)
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append)
e.Graphics.DrawRectangle(pen, rect)
Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.RotateTransform(28, MatrixOrder.Append);
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append);
e.Graphics.DrawRectangle(pen, rect);
下列範例會進行和上述範例中相同的呼叫,只不過順序顛倒。 最後的作業順序為先轉換、再旋轉,然後縮放,產生的結果和先縮放、再旋轉,然後轉換的結果完全不同。
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append)
e.Graphics.RotateTransform(28, MatrixOrder.Append)
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.DrawRectangle(pen, rect)
Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Append);
e.Graphics.RotateTransform(28, MatrixOrder.Append);
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.DrawRectangle(pen, rect);
使複合轉換中個別轉換的順序顛倒的方式之一,就是將一系列方法呼叫的順序顛倒。 控制作業順序的第二種方式是變更矩陣順序引數。 下列的範例與上述範例相同,除了 Append 已變更為 Prepend 以外。 矩陣乘法是依照 SRT 的順序,此處的 S、R 和 T 分別是指縮放、旋轉和轉換的矩陣。 複合轉換的順序是先縮放、再旋轉,然後轉換。
Dim rect As New Rectangle(0, 0, 50, 50)
Dim pen As New Pen(Color.FromArgb(128, 200, 0, 200), 2)
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Prepend)
e.Graphics.RotateTransform(28, MatrixOrder.Prepend)
e.Graphics.ScaleTransform(1.75F, 0.5F)
e.Graphics.DrawRectangle(pen, rect)
Rectangle rect = new Rectangle(0, 0, 50, 50);
Pen pen = new Pen(Color.FromArgb(128, 200, 0, 200), 2);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(150, 150, MatrixOrder.Prepend);
e.Graphics.RotateTransform(28, MatrixOrder.Prepend);
e.Graphics.ScaleTransform(1.75f, 0.5f);
e.Graphics.DrawRectangle(pen, rect);
最後這個範例的結果與這個主題中的第一個範例相同。 這是因為我們同時將方法呼叫的順序和矩陣乘法的順序都顛倒了。