変換の行列表現
m×n 行列は、m 行と n 列に配置された数値のセットです。 次の図は、いくつかの行列を示したものです。
個々の要素を追加することにより、同じサイズの 2 つの行列を加算できます。 次の図は、行列の加算の例を 2 つ示したものです。
m×n 行列は n×p 行列で乗算でき、結果は m×p 行列です。 1 つ目の行列の列数は、2 つ目の行列の行数と同じである必要があります。 たとえば、4 ×2 行列に 2 ×3 行列を掛けて、4 ×3 行列を生成できます。
平面内の点と行列の行と列は、ベクターと考えることができます。 たとえば、(2, 5) は 2 つのコンポーネントを持つベクターで、(3, 7, 1) は 3 つのコンポーネントを持つベクターです。 2 つのベクターのドット積は、次のように定義されます。
(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 です。 2 つのベクターのドット積は、別のベクターではなく、数値であることに注意してください。 また、ドット積を計算することができるのは、2 つのベクターのコンポーネント数が同じ場合に限られます。
A(i, j) を i番目 の行と j番目 の列の行列 A のエントリにしてみましょう。 たとえば、A(3, 2) は、3番目 の行と 2番目 の列の行列 A のエントリです。 A、B、および C が行列で、AB = C であるとすると、C のエントリは次のように計算されます。
C(i, j) = (A の i 行) • (B の j 列)
次の図は、行列の乗算の例をいくつか示したものです。
平面内の点を 1 × 2 行列と考える場合は、その点に 2 × 2 行列を掛けて変換できます。 次の図は、点 (2, 1) に適用されたいくつかの変換を示したものです。
前の図に示したすべての変換は、線形変換です。 変換など、他の特定の変換は線形ではなく、2 × 2 行列で乗算として表すことはできません。 たとえば、点 (2, 1) で開始し、それを 90 度回転し、x 方向に 3 単位平行移動し、y 方向に 4 単位平行移動したいとします。 これを実現するには、行列乗算の後に行列の加算を実行します。
線形変換 (2 × 2 行列による乗算) とそれに続く変換 (1 × 2 行列の加算) は、アフィン変換と呼ばれます。 アフィン変換を一対の行列に格納する代わりに、変換全体を 3 × 3 行列に格納します 。1 つは線形部分用で、もう 1 つは変換用です。 この作業を行うには、平面内の点を、ダミーの 3 番目の座標を持つ 1 × 3 行列に格納する必要があります。 通常は、3 つ目の座標をすべて 1 に設定するという方法が使用されます。 たとえば、点 (2, 1) は、行列 [2 1 1] によって表されます。 次の図は、単一の 3 × 3 行列による乗算として表されるアフィン変換 (90 度回転し、x 方向に 3 単位、y 方向に 4 単位を平行移動) を示しています。
前の例では、ポイント (2、 1) がポイント (2、6) にマップされています。 3 × 3 行列の 3 番目の列には、数値 0、0、1 が含まれていることに注意してください。 これは常に、アフィン変換の 3 × 3 行列の場合です。 重要なのは、列 1 と列 2 の 6 つの数値です。 行列の左上 2 × 2 部分は変換の線形部分を表し、3 番目の行の最初の 2 つのエントリは変換を表します。
Windows GDI+ では、アフィン変換を Matrix オブジェクトに格納できます。 アフィン変換を表す行列の 3 番目の列は常に (0, 0, 1) であるため、 Matrix オブジェクトを作成するときは、最初の 2 つの列に 6 つの数値のみを指定します。 ステートメント Matrix myMatrix(0.0f, 1.0f, -1.0f, 0.0f, 3.0f, 4.0f);
は、前の図に示したマトリックスを構築します。
複合変換
複合変換とは、変換を順番に実行していく、変換のシーケンスのことです。 次の一覧に示す行列と変換について考えてみましょう。
- 行列 A 90 度回転
- 行列 B x 方向の係数 2 によるスケール
- 行列 C y 方向に 3 単位を平行移動
行列 [2 1 1] で表される点 (2, 1) で始まり、A、B、C で乗算すると、ポイント (2,1) は一覧表示された順序で 3 つの変換を行います。
[2 1 1]ABC = [ –2 5 1]
複合変換の 3 つの部分を 3 つの別々の行列に格納するのではなく、A、B、C を乗算して、複合変換全体を格納する単一の 3 × 3 個の行列を取得できます。 ABC = D とした場合、点を D で乗算した結果は、A、B、C の順に乗算した結果と同じになります。
[2 1 1]D = [ –2 5 1]
次の図は、A、B、C、D の行列を示したものです。
複合変換の行列は、個々の変換行列を乗算することによって形成できるという事実は、アフィン変換の任意のシーケンスを単一の Matrix オブジェクトに格納できることを意味します。
注意
複合変換では、順序が重要となります。 通常、回転、拡大縮小、平行移動という順序での操作は、スケーリング、回転、平行移動という順序での操作でと同じではありません。 同様に、行列の乗算においても順序が重要となります。 通常、ABC は BAC と同じではありません。
Matrix クラスには、複合変換を構築するためのいくつかのメソッド (Matrix::Multiply、Matrix::Rotate、Matrix::RotateAt、Matrix::Scale、Matrix::Shear、Matrix::Translate) が用意されています。 次の例では、最初に 30 度回転し、次に y 方向に 2 の係数でスケーリングし、x 方向に 5 単位を平行移動する複合変換の行列を作成します。
Matrix myMatrix;
myMatrix.Rotate(30.0f);
myMatrix.Scale(1.0f, 2.0f, MatrixOrderAppend);
myMatrix.Translate(5.0f, 0.0f, MatrixOrderAppend);
以下の図は、この行列を示したものです。