変換順序が重要となる理由

1 つの Matrix オブジェクトには、1 つの変換または一連の変換を格納できます。 後者は複合変換と呼ばれます。 複合変換の行列は、個々の変換の行列を乗算することによって得られます。

複合変換の例

複合変換では、個々の変換の順序が重要になります。 たとえば、最初に回転し、拡大縮小してから、平行移動する場合と、最初に平行移動し、回転してから、拡大縮小する場合では、得られる結果が異なります。 GDI+ では、複合変換は左から右に構築されます。 S、R、T をそれぞれ拡大縮小、回転、拡大縮小の各行列とすると、積 SRT (この順序で) は、最初に拡大縮小し、回転してから、拡大縮小する複合変換の行列になります。 積 SRT によって生成される行列と、積 TRS によって生成される行列は異なります。

順序が重要である理由の 1 つは、回転や拡大縮小などの変換が、座標系の原点に対して行われるということです。 原点を中心にして配置されているオブジェクトの拡大縮小と、原点から離れた位置に移動されたオブジェクトの拡大縮小では、異なる結果が生成されます。 同様に、原点を中心にして配置されているオブジェクトの回転と、原点から離れた位置に移動されたオブジェクトの回転でも、異なる結果になります。

拡大縮小、回転、平行移動を (この順序で) 組み合わせて複合変換を作成する例を次に示します。 RotateTransform メソッドに渡される引数 Append は、拡大縮小の後で回転を行うことを示します。 同様に、TranslateTransform メソッドに渡される引数 Append は、回転の後で平行移動を行うことを示します。 AppendPrepend は、MatrixOrder 列挙型のメンバーです。

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.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.TranslateTransform(150, 150, MatrixOrder.Append);
e.Graphics.RotateTransform(28, MatrixOrder.Append);
e.Graphics.ScaleTransform(1.75f, 0.5f);
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)

複合変換で個々の変換の順序を逆にする方法の 1 つは、メソッドの呼び出しの順序を逆にすることです。 操作の順序を制御するもう 1 つの方法は、行列の順序引数を変更することです。 次の例は、前の例と同じですが、AppendPrepend に変更されている点が異なります。 行列の乗算は、SRT の順序で実行されます。S、R、T は、それぞれ拡大縮小、回転、平行移動の行列です。 複合変換の順序は、最初に拡大縮小、次に回転、最後に平行移動になります。

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);
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)

すぐ前の例の結果は、このトピックの最初の例の結果と同じです。 これは、メソッド呼び出しの順序と行列乗算の順序の両方を逆にしたためです。

関連項目