====== 同次変換・アフィン変換 練習問題 ====== ===== 2D・3D / DirectX11形式 ===== ---- ====== 導入:右から掛けるルールと左から掛けるルール ====== 3Dグラフィックスの行列計算では、資料やライブラリによって**点と行列の掛け方**が違う。 大きく分けると、次の2種類がある。 ^ 方式 ^ 点の書き方 ^ 掛け算の形 ^ よく見る場面 ^ | 列ベクトル方式 | 縦に書く | \[ P' = M P \] | 数学の教科書、OpenGL系の説明 | | 行ベクトル方式 | 横に書く | \[ P' = P M \] | DirectX系の説明 | このプリントでは、最終的に**DirectX11でよく使う行ベクトル方式**で練習する。 ただし、最初に2つの違いを確認しておく。 ---- ===== 1. 列ベクトル方式 ===== 列ベクトル方式では、点を縦に書く。 2Dの点 \(P(x, y)\) は、同次座標で次のように表す。 \[ P = \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \] 変換後の点は、行列を左から掛けて求める。 \[ P' = M P \] つまり、**行列が左、点が右**にある。 ---- ===== 2. 列ベクトル方式の平行移動 ===== 列ベクトル方式で、x方向に \(t_x\)、y方向に \(t_y\) 平行移動する行列は次の形になる。 \[ T = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix} \] 点に掛けると、次のようになる。 \[ P' = T P \] \[ \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \] 実際に掛け算すると、 \[ x' = 1 \times x + 0 \times y + t_x \times 1 \] \[ y' = 0 \times x + 1 \times y + t_y \times 1 \] したがって、 \[ x' = x + t_x \] \[ y' = y + t_y \] になる。 ---- ===== 3. 行ベクトル方式 ===== 行ベクトル方式では、点を横に書く。 2Dの点 \(P(x, y)\) は、同次座標で次のように表す。 \[ P = \begin{bmatrix} x & y & 1 \end{bmatrix} \] 変換後の点は、点を左から行列に掛けて求める。 \[ P' = P M \] つまり、**点が左、行列が右**にある。 ---- ===== 4. 行ベクトル方式の平行移動 ===== 行ベクトル方式で、x方向に \(t_x\)、y方向に \(t_y\) 平行移動する行列は次の形になる。 \[ T = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{bmatrix} \] 点に掛けると、次のようになる。 \[ P' = P T \] \[ \begin{bmatrix} x' & y' & 1 \end{bmatrix} = \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{bmatrix} \] 実際に掛け算すると、 \[ x' = x \times 1 + y \times 0 + 1 \times t_x \] \[ y' = x \times 0 + y \times 1 + 1 \times t_y \] したがって、 \[ x' = x + t_x \] \[ y' = y + t_y \] になる。 ---- ===== 5. 同じ変換でも行列の形が違う ===== 同じ「x方向に \(t_x\)、y方向に \(t_y\) 平行移動」でも、列ベクトル方式と行ベクトル方式では、行列の形が違う。 ==== 列ベクトル方式 ==== \[ \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix} \] ==== 行ベクトル方式 ==== \[ \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{bmatrix} \] 列ベクトル方式では、平行移動は**右端の列**に入る。 行ベクトル方式では、平行移動は**下の行**に入る。 ---- ===== 6. 掛け算のやり方の違い ===== ==== 列ベクトル方式 ==== 列ベクトル方式では、 \[ P' = M P \] である。 例えば、 \[ \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} \] を計算すると、 \[ x' = ax + by + c \] \[ y' = dx + ey + f \] \[ w' = gx + hy + i \] になる。 ---- ==== 行ベクトル方式 ==== 行ベクトル方式では、 \[ P' = P M \] である。 例えば、 \[ \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix} \] を計算すると、 \[ x' = xa + yd + 1g \] \[ y' = xb + ye + 1h \] \[ w' = xc + yf + 1i \] になる。 同じ行列に見えても、**どちら側から掛けるかで使われる成分が変わる**。 ---- ===== 7. 合成変換の順番の違い ===== 点に対して、次の順番で変換したいとする。 - 拡大縮小 \(S\) - 回転 \(R\) - 平行移動 \(T\) ---- ==== 列ベクトル方式の場合 ==== 列ベクトル方式では、 \[ P' = M P \] である。 実際の計算は次のようになる。 \[ P' = T R S P \] つまり、合成行列は、 \[ M = T R S \] である。 行列の見た目としては、**後に実行する変換ほど左側に来る**。 ---- ==== 行ベクトル方式の場合 ==== 行ベクトル方式では、 \[ P' = P M \] である。 実際の計算は次のようになる。 \[ P' = P S R T \] つまり、合成行列は、 \[ M = S R T \] である。 行列の見た目としては、**実行したい順番に左から右へ並べればよい**。 ---- ===== 8. このプリントで使うルール ===== このプリントでは、**DirectX11形式**として、次のルールで統一する。 ==== 点は行ベクトルで書く ==== \[ P = \begin{bmatrix} x & y & 1 \end{bmatrix} \] または、 \[ P = \begin{bmatrix} x & y & z & 1 \end{bmatrix} \] ==== 点は左から行列に掛ける ==== \[ P' = P M \] ==== 合成変換は、実行したい順番に行列を並べる ==== 例えば、 - 拡大縮小 - 回転 - 平行移動 なら、 \[ M = S R T \] である。 ---- ====== 2Dの同次座標 ====== 2次元の点 \(P(x, y)\) は、同次座標では次のように表す。 \[ P = \begin{bmatrix} x & y & 1 \end{bmatrix} \] 2Dのアフィン変換行列は、DirectX11形式では次の形になる。 \[ M = \begin{bmatrix} a & b & 0 \\ c & d & 0 \\ t_x & t_y & 1 \end{bmatrix} \] ---- ===== 2Dの基本変換行列 ===== ==== 平行移動 ==== \[ T = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ t_x & t_y & 1 \end{bmatrix} \] ==== 拡大縮小 ==== \[ S = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix} \] ==== 原点中心の回転 ==== このプリントでは、2D回転は反時計回りを正とする。 \[ R = \begin{bmatrix} \cos\theta & \sin\theta & 0 \\ -\sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} \] ---- ====== 第1部:2D同次変換 ====== ---- ===== 問題1:2D平行移動 ===== 点 \(P(2, 3)\) を、次のように平行移動する。 * x方向に \(+4\) * y方向に \(-1\) ==== 問い ==== - 平行移動行列 \(T\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P T \] ==== 問い ==== - 平行移動行列 \(T\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P T \] ==== 解答欄 ==== \[ T = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad) \] ---- ===== 問題2:2D拡大縮小 ===== 点 \(P(2, 3)\) を、次のように拡大縮小する。 * x方向に \(3\) 倍 * y方向に \(2\) 倍 ==== 問い ==== - 拡大縮小行列 \(S\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P S \] ==== 解答欄 ==== \[ S = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad) \] ---- ===== 問題3:2D回転 ===== 点 \(P(1, 0)\) を、原点を中心に反時計回りに \(90^\circ\) 回転する。 \[ \cos 90^\circ = 0 \] \[ \sin 90^\circ = 1 \] ==== 問い ==== - 回転行列 \(R\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P R \] ==== 解答欄 ==== \[ R = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad) \] ---- ===== 問題4:2D合成変換 ===== 点 \(P(1, 2)\) に対して、次の順番で変換する。 - x方向に \(2\) 倍、y方向に \(3\) 倍する - x方向に \(+5\)、y方向に \(-1\) 平行移動する DirectX11形式なので、合成行列は次の順番になる。 \[ M = S T \] ==== 問い ==== - 拡大縮小行列 \(S\) を書け。 - 平行移動行列 \(T\) を書け。 - 合成行列 \(M = S T\) を求めよ。 - 点 \(P\) の変換後の座標を求めよ。 ==== 解答欄 ==== \[ S = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] \[ T = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] \[ M = S T = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad) \] ---- ===== 問題5:2D合成変換と順番の違い ===== 点 \(P(1, 1)\) に対して、次の2通りの変換を行う。 ==== A ==== - x方向に \(+3\)、y方向に \(0\) 平行移動する - 全体を \(2\) 倍に拡大する ==== B ==== - 全体を \(2\) 倍に拡大する - x方向に \(+3\)、y方向に \(0\) 平行移動する ==== 問い ==== - Aの合成行列 \(M_A\) を求めよ。 - Bの合成行列 \(M_B\) を求めよ。 - AとBそれぞれの変換後の座標を求めよ。 - 結果が違う理由を説明せよ。 ==== 解答欄 ==== Aの合成行列: \[ M_A = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] Aの変換後: \[ (\quad,\quad) \] Bの合成行列: \[ M_B = \begin{bmatrix} \quad & \quad & \quad \\ \quad & \quad & \quad \\ \quad & \quad & \quad \end{bmatrix} \] Bの変換後: \[ (\quad,\quad) \] 理由: > ---- ====== 第2部:3D同次変換 ====== ---- ===== 3Dの同次座標 ===== 3次元の点 \(P(x, y, z)\) は、同次座標では次のように表す。 \[ P = \begin{bmatrix} x & y & z & 1 \end{bmatrix} \] 3Dのアフィン変換行列は、DirectX11形式では次の形になる。 \[ M = \begin{bmatrix} a & b & c & 0 \\ d & e & f & 0 \\ g & h & i & 0 \\ t_x & t_y & t_z & 1 \end{bmatrix} \] ---- ===== 3Dの基本変換行列 ===== ==== 平行移動 ==== \[ T = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ t_x & t_y & t_z & 1 \end{bmatrix} \] ==== 拡大縮小 ==== \[ S = \begin{bmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \] ==== Y軸回転 ==== このプリントでは、DirectXの左手系を前提とする。 \[ R_y = \begin{bmatrix} \cos\theta & 0 & -\sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ \sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \] \(90^\circ\) の場合は次のようになる。 \[ R_y = \begin{bmatrix} 0 & 0 & -1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \] ---- ===== 問題6:3D平行移動 ===== 点 \(P(1, 2, 3)\) を、次のように平行移動する。 * x方向に \(+4\) * y方向に \(-2\) * z方向に \(+1\) ==== 問い ==== - 平行移動行列 \(T\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P T \] ==== 解答欄 ==== \[ T = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad,\quad) \] ---- ===== 問題7:3D拡大縮小 ===== 点 \(P(1, 2, 3)\) を、次のように拡大縮小する。 * x方向に \(2\) 倍 * y方向に \(3\) 倍 * z方向に \(4\) 倍 ==== 問い ==== - 拡大縮小行列 \(S\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P S \] ==== 解答欄 ==== \[ S = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad,\quad) \] ---- ===== 問題8:3D Y軸回転 ===== 点 \(P(1, 0, 0)\) を、Y軸まわりに \(90^\circ\) 回転する。 ==== 問い ==== - Y軸回転行列 \(R_y\) を書け。 - 次の計算を行い、変換後の座標を求めよ。 \[ P' = P R_y \] ==== 解答欄 ==== \[ R_y = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad,\quad) \] ---- ===== 問題9:3D合成変換 ===== 点 \(P(1, 2, 3)\) に対して、次の順番で変換する。 - 全体を \(2\) 倍に拡大する - Y軸まわりに \(90^\circ\) 回転する - x方向に \(+3\)、y方向に \(+1\)、z方向に \(+2\) 平行移動する DirectX11形式なので、合成行列は次の順番になる。 \[ M = S R_y T \] ==== 問い ==== - 拡大縮小行列 \(S\) を書け。 - Y軸回転行列 \(R_y\) を書け。 - 平行移動行列 \(T\) を書け。 - 合成行列 \(M = S R_y T\) を求めよ。 - 点 \(P\) の変換後の座標を求めよ。 ==== 解答欄 ==== \[ S = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] \[ R_y = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] \[ T = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] \[ M = S R_y T = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] 変換後の座標: \[ (\quad,\quad,\quad) \] ---- ===== 問題10:3D合成変換と順番の違い ===== 点 \(P(1, 0, 0)\) に対して、次の2通りの変換を行う。 ==== A ==== - x方向に \(+5\) 平行移動する - Y軸まわりに \(90^\circ\) 回転する ==== B ==== - Y軸まわりに \(90^\circ\) 回転する - x方向に \(+5\) 平行移動する ==== 問い ==== - Aの合成行列 \(M_A\) を求めよ。 - Bの合成行列 \(M_B\) を求めよ。 - AとBそれぞれの変換後の座標を求めよ。 - 結果が違う理由を説明せよ。 ==== 解答欄 ==== Aの合成行列: \[ M_A = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] Aの変換後: \[ (\quad,\quad,\quad) \] Bの合成行列: \[ M_B = \begin{bmatrix} \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \\ \quad & \quad & \quad & \quad \end{bmatrix} \] Bの変換後: \[ (\quad,\quad,\quad) \] 理由: >