Chapter 01

線形代数 ベクトル編

mebiusbox
mebiusbox
2021.02.24に更新

📌 はじめに

CGプログラミングで最もよく使われる数学に線形代数があります.線形代数ではベクトル,行列といったおなじみの要素が入っていますし,行列式もよく使います.線形代数の範囲はもっと広いのですが,ここでは基礎的な部分のみを取り上げて,なるべくわかりやすく説明していきたいと思います.用語もなるべく少なくしているので,興味を持ったり,もっと知りたくなった人は,参考書を見たり,検索したりすることをお勧めします.今回の内容は,あくまでCGプログラミングに興味のある読者を対象にしていますが,コードは一切登場せず,数式が沢山出てきます.1つ1つゆっくり確認しながら読んでもらえるといいかなと思います.

今回の内容は村上雅人著「なるほど線形代数」にかなり影響されています.この本は個人的に大変わかりやすいと思いますのでお勧めします.ただし,線形代数の本は,線形代数は量子力学で大活躍するといった謳い文句で始まることが多く,この本もその1冊です.今回はあくまでCGプログラミングを目的としているので,ベクトルの内積や外積などに,ほんの少しCGプログラミングに関する説明を追加しています.

ここで説明する内容は主に,ベクトル,行列,行列式の3つの要素です.それでは始めてみましょう.

📌 ベクトルは数の集まり

ベクトルといえば,多くの人が3次元ベクトルを思い浮かぶかもしれません.もしくは2次元ベクトルかもしれませんね.頭の中では3次元もしくは2次元座標上に矢印が描かれていることでしょう.それはベクトルで間違いありませんが,あくまでベクトルの種類の1つです.3次元空間上のある点を表すには3つの数が必要です.2次元平面上の点なら2つの数です.3次元を XYZ 軸で表すとある点は (x,y,z) の座標で表せますね.2次元なら (x,y) です.2次元平面や3次元空間は幾何的に想像しやすいですが,例えば,3次元空間に「時間」を追加した4次元を考えることも出来ます.この場合は,4つの数が必要になります.時間を t とすれば,(x,y,z,t) と表せそうです.流石に4次元となるとなかなか想像できません.今は2次元や3次元座標上のある点を例にしましたが,別に座標である必要はなく,例えば,あなたのお財布の中に500円硬貨が1枚,100円硬貨が4枚,10円硬貨が2枚,1円硬貨が6枚入っていたら,(1,4,2,6) という4つの数で表わせそうです.このように,複数の数を集めたものを ベクトル といいます.ちなみに,私の財布の中をベクトルで表すと,(0,6,1,4)です.このベクトルは500円硬貨が0枚,100円硬貨が6枚,10円硬貨が1枚,1円硬貨が4枚だとわかりますね.ベクトルは4つ以上の数も扱えますので,n個の数を持つベクトルもあるわけです.

📌 ベクトルの種類

ベクトルはn次元の数を持つことができるわけなのですが,平面(2次元)や空間(3次元)を扱うことが多いです.平面や空間上のある点を原点からの値で表したベクトル(座標という)を 位置ベクトル といいます.また,原点ではなく,ある位置から別の位置への値を表すベクトルもあります.これは向きと大きさを表し, 幾何ベクトル といいます.そして,平面や空間ではなく,さきほどの硬貨の説明で使ったベクトルは単に数の集まりを表しているので 数ベクトル といいます.CGプログラミングでは位置ベクトルと幾何ベクトルを主に使います.

📌 ベクトルの表記

ベクトルは a,b と太字にしたり,\vec{a},\vec{b}と矢印をつけて表します.また,始点をA,終点をBとすると\vec{AB}と表すこともあります.この文書では矢印をつけてベクトルを表記します.例えば,次のようなベクトルを考えます.

\vec{a} = \begin{pmatrix}2\\3\end{pmatrix} \qquad \vec{b} = \begin{pmatrix}4\\1\end{pmatrix}

ベクトルの個々の数を 成分 といい,このように成分を並べて表示することを 成分表示 といいます.この2次元ベクトル\vec{a},\vec{b}を位置ベクトルとして考えると,それぞれXY平面上の点に対応します.

2018-08-18_23h29_43

また,幾何ベクトルとして考えるとベクトル\vec{a}X方向に2,Y方向に3進むベクトル,ベクトル\vec{b}X方向に4,Y方向に1進むベクトルとなります.幾何ベクトルの場合は始点が原点ではなく,任意の点が始点になり,大きさと方向が同じベクトルはすべて同じベクトルと考えられます.

2018-08-18_23h29_49

幾何ベクトルは方向と大きさを表すベクトルです.方向はXYの値で表されていますが,大きさはどうでしょうか.この大きさはピタゴラスの定理を使って求めることができます.ベクトルの大きさは,絶対値記号を使って|\vec{a}|,|\vec{b}|と表します.

|\vec{a}| = \sqrt{2^2+3^2} = \sqrt{13} \qquad |\vec{b}| = \sqrt{4^2+1^2} = \sqrt{17}

2次元ベクトルを一般化して書くと

\vec{a} = \begin{pmatrix}a_x\\a_y\end{pmatrix}

a_xx成分,a_yy成分を表します.上記のように縦に並べたベクトルを 列ベクトル といいます.また,数を横に並べたベクトル

\vec{a} = \begin{pmatrix}a_x & a_y\end{pmatrix}

行ベクトル といいます.2次元ベクトルは座標(a_x,a_y)で表現することも,長さとx軸の正方向からの角度(r,\theta)で表現することもできます.rは大きさと同じなのでr=|\vec{a}|です.

2018-08-18_23h29_54

上図から次の関係がわかります.

|\vec{a}| = \sqrt{a_x^2+a_y^2} \qquad a_x = |\vec{a}|\cos\theta \qquad a_y = |\vec{a}|\sin\theta \qquad

📌 ベクトルの演算

ベクトルの加算は成分ごとに行います.

\vec{a}+\vec{b} = \begin{pmatrix}2\\3\end{pmatrix} + \begin{pmatrix}1\\4\end{pmatrix} = \begin{pmatrix}3\\7\end{pmatrix}

減算も同様に行えます.

\vec{a}-\vec{b} = \begin{pmatrix}2\\3\end{pmatrix} - \begin{pmatrix}1\\4\end{pmatrix} = \begin{pmatrix}1\\-1\end{pmatrix}

同じベクトルでの引き算は

\vec{a}-\vec{a} = \begin{pmatrix}2\\3\end{pmatrix} - \begin{pmatrix}2\\3\end{pmatrix} = \begin{pmatrix}0\\0\end{pmatrix}

これは数字の0と同じように,成分がすべて0のベクトルとなり,ゼロベクトルといいます.-\vec{a}\vec{a}と同じ大きさで,方向が逆のベクトルです.

ベクトルの加算では順番を変えても同じ結果になります(交換法則).

\vec{a}+\vec{b} = \vec{b} + \vec{a}

同じベクトルを足し合わせると

\begin{aligned} \vec{a}+\vec{a} &= \begin{pmatrix}2\\3\end{pmatrix}+\begin{pmatrix}2\\3\end{pmatrix} = \begin{pmatrix}4\\7\end{pmatrix} \\ \vec{a}+\vec{a}+\vec{a} &= \begin{pmatrix}2\\3\end{pmatrix}+\begin{pmatrix}2\\3\end{pmatrix}+\begin{pmatrix}2\\3\end{pmatrix} = \begin{pmatrix}6\\10\end{pmatrix} \end{aligned}

という関係なので,ベクトルを整数倍するときは成分ごとに整数倍すればよいことがわかります.nを適当な実数とすれば

n\vec{a} = \begin{pmatrix}na_x\\na_y\end{pmatrix}

となります.ここでさらに任意の実数mを使って

(m+n)\vec{a} = \begin{pmatrix}(m+n)a_x\\(m+n)a_y\end{pmatrix} = \begin{pmatrix}ma_x\\ma_y\end{pmatrix}+\begin{pmatrix}na_x\\na_y\end{pmatrix} = m\begin{pmatrix}a_x\\a_y\end{pmatrix}+n\begin{pmatrix}a_x\\a_y\end{pmatrix} = m\vec{a}+n\vec{a}

と計算できるから

\begin{aligned} (m+n)\vec{a} &= m\vec{a}+n\vec{a} \\ (m-n)\vec{a} &= m\vec{a}-n\vec{a} \end{aligned}

となり,分配法則が成り立つことがわかります.

次に,複数のベクトルの和を考えてみます.今,3つのベクトル

\vec{a} = \begin{pmatrix}a_x\\a_y\end{pmatrix} \quad \vec{b} = \begin{pmatrix}b_x\\b_y\end{pmatrix} \quad \vec{c} = \begin{pmatrix}c_x\\c_y\end{pmatrix}

があります.この3つのベクトルの和は

\vec{a}+\vec{b}+\vec{c} = \begin{pmatrix}a_x\\a_y\end{pmatrix}+\begin{pmatrix}b_x\\b_y\end{pmatrix}+\begin{pmatrix}c_x\\c_y\end{pmatrix} = \begin{pmatrix}a_x+b_x+c_x\\a_y+b_y+c_y\end{pmatrix}

となります.これは

\vec{a}+\vec{b}+\vec{c} = (\vec{a}+\vec{b})+\vec{c} = \begin{pmatrix}a_x+b_x\\a_y+b_y\end{pmatrix}+\begin{pmatrix}c_x\\c_y\end{pmatrix} = \begin{pmatrix}a_x+b_x+c_x\\a_y+b_y+c_y\end{pmatrix}

という形にしても計算できます.また,

\vec{a}+\vec{b}+\vec{c} = \vec{a}+(\vec{b}+\vec{c}) = \begin{pmatrix}a_x\\a_y\end{pmatrix}+\begin{pmatrix}b_x+c_x\\b_y+c_y\end{pmatrix} = \begin{pmatrix}a_x+b_x+c_x\\a_y+b_y+c_y\end{pmatrix}

としても同じ答えが得られます.よって

(\vec{a}+\vec{b})+\vec{c} = \vec{a}+(\vec{b}+\vec{c})

という結合法則が成り立ちます.このようにベクトルの加減算,実数倍の演算は自由に行うことができます.
そして,これまで2次元ベクトルの演算を見てきましたが,数が増えても同じルールで計算することができるので,3次元やn次元のベクトルに対しても同様の演算が出来ます.

📌 ベクトルの乗算

ベクトルの演算のところで実数倍の計算を行いました.ベクトルが数の集まりであるのに対して,1つの実数を スカラー といいます.ベクトルの大きさ|\vec{a}|n\vec{a}nはスカラーです.
ベクトルとスカラーの乗算,つまりベクトル\times実数の乗算はベクトルの大きさを変えます.また,負の実数を乗算すると大きさが変化するとともに,ベクトルの方向は反転します.
それではベクトルとベクトルの乗算を考えてみます.ベクトルの乗算には2種類あって, 内積外積 があります.内積と外積はベクトル演算に大変便利な特性を持っていて,CGプログラミングでも頻繁に使うことになります.元々は四元数の積から来ているようですので,興味があれば四元数と内積で検索してみてください.ここではまず定義から見ていくことにします.

📌 内積

いま,2つのベクトル

\vec{a} = \begin{pmatrix}a_x\\a_y\end{pmatrix} \quad \vec{b} = \begin{pmatrix}b_x\\b_y\end{pmatrix}

を考えます.下図の左のように,この2つのベクトルがなす角を\thetaとしたとき

2018-08-18_23h30_02

内積は次のようになります.

\vec{a}\cdot\vec{b} = |\vec{a}||\vec{b}|\cos\theta

この計算はベクトル\timesベクトルですが,結果はスカラーになります.

2018-08-18_23h30_10

上図のように,ベクトル\vec{a},\vec{b}x軸となす角を\alpha,\betaとすると次の関係が成り立つことがわかります.

\cos\alpha = \frac{a_x}{|\vec{a}|} \quad \cos\beta = \frac{b_x}{|\vec{b}|} \quad \sin\alpha = \frac{a_y}{|\vec{a}|} \quad \sin\beta = \frac{b_y}{|\vec{b}|}

これを先程の式に代入すると

\begin{aligned} \vec{a}\cdot\vec{b} &= |\vec{a}||\vec{b}|(\cos\alpha\cos\beta + \sin\alpha\sin\beta) \\ &= |\vec{a}||\vec{b}|\left(\frac{a_x b_x}{|\vec{a}||\vec{b}|} +\frac{a_y b_y}{|\vec{a}||\vec{b}|}\right) \\ &= a_x b_x + a_y b_y \end{aligned}

同じベクトル同士の内積は

\begin{aligned} \vec{a}\cdot\vec{a} &= |\vec{a}||\vec{a}|\cos 0 = |\vec{a}|^2 \\ \vec{a}\cdot\vec{a} &= a_x a_x + a_y a_y = a_x^2+a_y^2 \end{aligned}

となり,ベクトルの大きさの二乗となります.内積を使ってベクトルの大きさを

|\vec{a}| = \sqrt{\vec{a}\cdot\vec{a}}

と表わせます.これを ノルム といいます.ベクトルの大きさ(長さ)とノルムの値は同じですが,4次元以上のベクトルの大きさというと想像しにくいです.そのかわり,ノルムといえば誤解なく伝わります.ノルムは||\vec{a}||と表記することもあります.

内積は行ベクトルと列ベクトルを使って次のようにも表わせます.

\vec{a}\cdot\vec{b} = \begin{pmatrix}a_x & a_y\end{pmatrix}\begin{pmatrix}b_x\\b_y\end{pmatrix} = a_x b_x + a_y b_y

内積を使えば,2つのベクトルがなす角度を求めることができます.内積の式を変形して

\cos\theta = \frac{\vec{a}\cdot\vec{b}}{|\vec{a}||\vec{b}|}

ここで

\begin{aligned} \vec{a}\cdot\vec{b} &= a_x b_x + a_y b_y \\ |\vec{a}| &= \sqrt{a_x^2+a_y^2} \\ |\vec{b}| &= \sqrt{b_x^2+b_y^2} \end{aligned}

という関係にあるので,代入すると

\cos\theta = \frac{a_x b_x + a_y b_y}{\sqrt{a_x^2+a_y^2} \sqrt{b_x^2+b_y^2}}

となり,角度を求めることができます.

次に,3次元の内積を見てみましょう.次のような3次元ベクトルを考えます.

\vec{a} = \begin{pmatrix}a_x\\a_y\\a_z\end{pmatrix} \quad \vec{b} = \begin{pmatrix}b_x\\b_y\\b_z\end{pmatrix}

この内積は

\vec{a}\cdot\vec{b} = \begin{pmatrix}a_x & a_y & a_z\end{pmatrix}\begin{pmatrix}b_x\\b_y\\b_z\end{pmatrix} = a_x b_x + a_y b_y + a_z b_z

となります.4次元以上の内積も結果は予想できそうですね.最初の方で,ベクトルが数の集まりということを説明しました.そのときに硬貨の枚数をベクトルで表したことを覚えていますか? もう一度このベクトルを見てましょう.あなたのお財布の中にある硬貨の枚数をベクトルで表すと

\vec{a} = \begin{pmatrix}1 & 4 & 2 & 6\end{pmatrix}

でした.ここで,硬貨の額面をベクトルにすると

\vec{b} = \begin{pmatrix}500 & 100 & 10 & 1 \end{pmatrix}

となります.これらの内積を計算すると

\vec{a}\cdot\vec{b} = \begin{pmatrix}1 & 4 & 2 & 6\end{pmatrix} \begin{pmatrix}500\\100\\10\\1\end{pmatrix} = 1\times 500 + 4\times 100 + 2\times 10 + 6\times 1 = 926

というように総額が求まりました.2次元や3次元の位置ベクトルや幾何ベクトルをよく扱いますが,この硬貨のベクトルのように数ベクトルにおける内積のイメージを掴んでおくことも大事です.

📌 外積

内積ではベクトル\timesベクトルを計算するとスカラーになりました.外積はベクトル\timesベクトルで結果がベクトルになります.こちらの方が直感的ではありますが,外積で求まるベクトルは最初はわかりづらいかもしれません.説明が天下り的になってしまいますが,1つ1つ確認しながら外積を見ていきましょう.

まず,外積は3次元ベクトルでのみ定義されます.よって,ここでのベクトルは3次元ベクトルです.次に外積の定義は次のようになっています.

\vec{a}\times\vec{b} = \vec{c}

ベクトル\vec{a},\vec{b}のなす角を\thetaとすると,その大きさは

|\vec{c}| = |\vec{a}||\vec{b}|\sin\theta

となります.下図のように,この大きさは\vec{a},\vec{b}がつくる平行四辺形の面積になります.

2018-08-18_23h30_20

また,\vec{c}の向きは,ベクトル\vec{a},\vec{b}のそれぞれに直交する向きになります.たとえば,\vec{a},\vec{b}xy平面にあるとすると,\vec{c}z軸方向を向きます.\vec{c}の方向はベクトルをかける順番によって変化します.それは右ねじの法則や右手系に準拠していて,xy平面を上からみたときに,ベクトルをかける順番が右回りなら奥に,左回りなら手前に向かうベクトルとなります.

2018-08-18_23h30_24

外積はベクトルをかける順番によって符号が変わります.

\vec{b}\times\vec{a} = -\vec{c}

つまり,交換法則が成り立ちません.

\vec{a}\times\vec{b} \neq \vec{b}\times\vec{a}

外積と内積を比べてみると,内積は2つのベクトルが平行の場合(\cos 0 = 1)値がもっとも大きくなりますが,外積はベクトルが並行の場合(\sin 0=0)大きさがもっとも小さくなります.逆にベクトルが直交しているとき,内積は0で,外積の大きさは最も大きくなります.

外積をもっと詳しく見ていく上でいくつか準備が必要です.用語が多く出てきますので,確認しながら読み進んでください.まず,一度xy平面について考えてみます.下図のように互いに平行でないベクトル\vec{a},\vec{b}があります(このようなベクトルを 線形独立 といいます).

2018-08-18_23h30_31

すると,適当な実数m,nを使ってXY平面上にあるすべてのベクトルを次のように表わせます.

\vec{p} = m\vec{a}+n\vec{b}

下図のように,加減算や符号を反転させてXY平面上を網羅できることがわかります.

2018-08-18_23h30_37

このような結合を 線形結合 または 1次結合 といいます.2次元空間では互いに平行ではないベクトルが2つあれば,その線形結合ですべての平面を表すことができます.この関係は3次元でもそのまま使えて,互いに平行でないベクトルが3つあればxyz空間上にあるベクトルは適当な実数m,n,kを使って

\vec{p} = m\vec{a}+n\vec{b}+k\vec{c}

となります.このようにベクトルの線形結合で張ることのできる空間を 線形空間 ,または ベクトル空間 といいます.もちろん,n次元に対しても同様です.

線形結合で2次元平面や3次元空間のすべてのベクトルを網羅できることがわかりました.任意の平行でないベクトルを2つもしくは3つあればいいわけですが,ここで基本的なベクトルを使うと,線形結合がよりわかりやすくなります.そのようなベクトルを 基本ベクトル といいます.具体的には,下図のように,x,y,z軸に沿った大きさが1のベクトルを使います.

2018-08-18_23h30_45

このような大きさが1のベクトルを 単位ベクトル といいます.単位ベクトルを列ベクトルで表記すると,2次元の場合は

\vec{e}_x = \begin{pmatrix}1\\0\end{pmatrix} \quad \vec{e}_y = \begin{pmatrix}0\\1\end{pmatrix}

また,3次元の場合は

\vec{e}_x = \begin{pmatrix}1\\0\\0\end{pmatrix} \quad \vec{e}_y = \begin{pmatrix}0\\1\\0\end{pmatrix} \quad \vec{e}_z = \begin{pmatrix}0\\0\\1\end{pmatrix}

となります.この単位ベクトルを使うと,座標の点を位置ベクトルとすれば,単位ベクトルの係数がそのまま座標になります.このような単位ベクトルを 基本ベクトル または 基底 といいます.たとえば,2次元の座標(2,1) を単位ベクトルの線形結合で表すと

\vec{p} = 2\vec{e}_x+1\vec{e}_y = 2\begin{pmatrix}1\\0\end{pmatrix}+1\begin{pmatrix}0\\1\end{pmatrix} = \begin{pmatrix}2\\0\end{pmatrix}+\begin{pmatrix}0\\1\end{pmatrix} = \begin{pmatrix}2\\1\end{pmatrix}

となります.一般的に

\vec{a} = \begin{pmatrix}a_x\\a_y\end{pmatrix}

というベクトルは

\vec{a} = \vec{a}_x\vec{e}_x + \vec{a}_y\vec{e}_y

と書けます.3次元ベクトルも

\vec{a} = \vec{a}_x\vec{e}_x + \vec{a}_y\vec{e}_y + \vec{a}_z\vec{e}_z

となります.これら基本ベクトルに対して内積を使うと

\begin{aligned} \vec{e}_x\cdot\vec{e}_x &= 1 \\ \vec{e}_x\cdot\vec{e}_y &= 0 \\ \vec{e}_x\cdot\vec{e}_z &= 0 \end{aligned}

という関係になり,外積に対しては

\begin{aligned} \vec{e}_x\times\vec{e}_y &= \vec{e}_z \\ \vec{e}_y\times\vec{e}_z &= \vec{e}_x \\ \vec{e}_z\times\vec{e}_x &= \vec{e}_y \end{aligned}
\vec{e}_x\times\vec{e}_x = \vec{e}_y\times\vec{e}_y = \vec{e}_z\times\vec{e}_z = \begin{pmatrix}0\\0\\0\end{pmatrix} = 0

という関係になります.ここで

\vec{a} = \begin{pmatrix}a_x\\a_y\end{pmatrix} \quad \vec{b} = \begin{pmatrix}b_x\\b_y\end{pmatrix}

という2つのベクトルの内積を単位ベクトルを使って計算すると

\begin{aligned} \vec{a} &= a_x \vec{e}_x + a_y\vec{e}_y \\ \vec{b} &= b_x \vec{e}_x + b_y\vec{e}_y \end{aligned}

となり

\vec{a}\cdot\vec{b} = \left(a_x \vec{e}_x+a_y\vec{e}_y\right)\cdot\left(b_x \vec{e}_x+b_y\vec{e}_y\right)

計算すると

\begin{aligned} \vec{a}\cdot\vec{b} &= \left(a_x \vec{e}_x+a_y\vec{e}_y\right)\cdot\left(b_x \vec{e}_x+b_y\vec{e}_y\right) \\ &= a_x b_x(\vec{e}_x\cdot\vec{e}_x) + a_x b_y(\vec{e}_x\cdot\vec{e}_y) + a_y b_x(\vec{e}_y\cdot\vec{e}_x) + a_y b_y(\vec{e}_y\cdot\vec{e}_y) \\ &= a_x b_x \times 1 + a_x b_y \times 0 + a_y b_x \times 0 + a_y b_y \times 1 \\ &= a_x b_x + a_y b_y \end{aligned}

ベクトルの内積が得られていることがわかります.さらに,任意のベクトル\vec{a}と単位ベクトルの内積をとると,そのベクトルの成分を求めることができます.

\begin{aligned} \vec{a}\cdot\vec{e}_x &= \begin{pmatrix}a_x&a_y\end{pmatrix}\begin{pmatrix}1\\0\end{pmatrix} = a_x\cdot 1 + a_y\cdot 0 = a_x \\ \vec{a}\cdot\vec{e}_y &= \begin{pmatrix}a_x&a_y\end{pmatrix}\begin{pmatrix}0\\1\end{pmatrix} = a_x\cdot 0 + a_y\cdot 1 = a_y \end{aligned}

これで外積に必要な準備は出来ました.外積について,基本ベクトルを使って計算してみます.つぎの2つのベクトルを考えます.

\vec{a} = \begin{pmatrix}a_x\\a_y\\a_z\end{pmatrix} \quad \vec{b} = \begin{pmatrix}b_x\\b_y\\b_z\end{pmatrix}

これらベクトルを基本ベクトルを使って

\begin{aligned} \vec{a} &= a_x\vec{e}_x + a_y\vec{e}_y + a_z\vec{e}_z \\ \vec{b} &= b_x\vec{e}_x + b_y\vec{e}_y + b_z\vec{e}_z \end{aligned}

となります.そして,ベクトル\vec{a}\vec{b}の外積は

\begin{aligned} \vec{a}\times\vec{b} &= \left(a_x\vec{e}_x + a_y\vec{e}_y + a_z\vec{e}_z\right)\times\left(b_x\vec{e}_x + b_y\vec{e}_y + b_z\vec{e}_z\right) \\ &= a_x b_x \left(\vec{e}_x\times\vec{e}_x\right) + a_x b_y \left(\vec{e}_x\times\vec{e}_y\right) + a_x b_z \left(\vec{e}_x\times\vec{e}_z\right) \\ &\quad + a_y b_x \left(\vec{e}_y\times\vec{e}_x\right) + a_y b_y \left(\vec{e}_y\times\vec{e}_y\right) + a_y b_z \left(\vec{e}_y\times\vec{e}_z\right) \\ &\quad + a_z b_x \left(\vec{e}_z\times\vec{e}_x\right) + a_z b_y \left(\vec{e}_z\times\vec{e}_y\right) + a_z b_z \left(\vec{e}_z\times\vec{e}_z\right) \\ &= a_x b_x \times 0 + a_x b_y \vec{e}_z - a_x b_z \vec{e}_y \\ &\quad - a_y b_x \vec{e}_z + a_y b_y \times 0 + a_y b_z \vec{e}_x \\ &\quad + a_z b_x \vec{e}_y - a_z b_y \vec{e}_x + a_z b_z \times 0 \\ &= (a_y b_z - a_z b_y)\vec{e}_x + (a_z b_x - a_x b_z)\vec{e}_y + (a_x b_y - a_y b_x)\vec{e}_z \end{aligned}

これを列ベクトルに書き直すと

\vec{a}\times\vec{b} = \begin{pmatrix}a_y b_z - a_z b_y \\ a_z b_x - a_x b_z \\ a_x b_y - a_y b_x\end{pmatrix}

となります.

📌 正規直交化基底ベクトル

つぎのベクトルを線形空間の基底のひとつにする場合を考えます.

\vec{a} = \begin{pmatrix}a_x\\a_y\\a_z\end{pmatrix}

基底にするには,このベクトルを単位ベクトルにする必要があります.つまり,大きさを1にします.そのためには,ベクトルの各成分をそのベクトルの大きさで割ります.

\vec{e}_a = \frac{\vec{a}}{|\vec{a}|}

このような操作を 正規化 といいます.今は3次元ベクトルを考えているので,基底ベクトルはあと2つ必要です.これは内積を使って任意に求めることができます.ベクトル \vec{e}_ a と線形独立な(平行でない)ベクトル\vec{b}を考えます.つぎに,基底ベクトル\vec{e}_aとの内積を計算して

\vec{e}_a\cdot\vec{b} = k

kが得られたとします.ここで,新たに

\vec{b}' = \vec{b} - k\vec{e}_a

というベクトルをつくります.このベクトルと基底ベクトル\vec{e}_aとの内積を計算すると

\vec{e}_a\cdot\vec{b}' = \vec{e}_a\cdot\vec{b}-k\vec{e}_a\cdot\vec{e}_a = k-k = 0

内積の値が0なので,この2つのベクトルは直交関係になっています.ベクトル\vec{b}'を基底とするために正規化をします.

\vec{e}_b = \frac{\vec{b}'}{|\vec{b}'|}

残りの基底ベクトルも内積を使って求められます.基底ベクトル\vec{e}_a,\vec{e}_bと線形独立なベクトル\vec{c}を決めて,2つの基底ベクトルとの内積をとります.

\vec{e}_a\cdot\vec{c} = l \qquad \vec{e}_b\cdot\vec{c} = m

この l,mを使って

\vec{c}' = \vec{c}-l\vec{e}_a-m\vec{e}_b

というベクトルを作ります.同じように基底ベクトルとの内積をとると

\begin{aligned} \vec{e}_a\cdot\vec{c}' &= \vec{e}_a\cdot\vec{c} - l\vec{e}_a\cdot\vec{e}_a - m\vec{e}_a\cdot\vec{e}_b = l-l-0 = 0 \\ \vec{e}_b\cdot\vec{c}' &= \vec{e}_b\cdot\vec{c} - l\vec{e}_b\cdot\vec{e}_a - m\vec{e}_b\cdot\vec{e}_b = m-m-0 = 0 \end{aligned}

となり,ベクトル\vec{c}'が2つの基底ベクトルと直交関係にあることがわかります.このベクトルも基底とするために正規化します.

\vec{e}_c = \frac{\vec{c}'}{|\vec{c}'|}

これで3つの基底ベクトル\vec{e}_a, \vec{e}_b, \vec{e}_cが得られました.このような基底ベクトルを 正規直交化基底ベクトル といいます.また,内積を使って基底ベクトルをつくる方法を シュミットの正規直交化法 または グラム・シュミットの直交化法 と呼びます.

📌 内積の特性

それではCGプログラミングでどのように内積や外積が使われるのか,簡単に紹介していきます.まずは内積からです.すでに説明しているものも含まれていますので復習のつもりで確認してみてください.また,CGに関する用語についてはある程度理解していることを前提としています.

ベクトル間の角度

2つのベクトルがなす角度(\theta)を求められます.式で表すと

\cos\theta = \frac{\vec{a}\cdot\vec{b}}{|\vec{a}||\vec{b}|}

となります.2次元ベクトルの場合

\cos\theta = \frac{a_x b_x + a_y b_y}{\sqrt{a_x^2+a_y^2} \sqrt{b_x^2+b_y^2}}

3次元ベクトルの場合

\cos\theta = \frac{a_x b_x + a_y b_y + a_z b_z}{\sqrt{a_x^2+a_y^2+a_z^2} \sqrt{b_x^2+b_y^2+b_z^2}}

となります.

次に2つのベクトルがお互いに直交しているかがわかります.内積の定義を確認してみると

\vec{a}\cdot\vec{b} = |\vec{a}||\vec{b}|\cos\theta

直交しているということは2つのベクトル間の角度が90度となり,\cos\thetaの値が0になります.よって,内積の値が0なら直交しています.あと,2つのベクトルがどれくらい同じ方向を向いているかがわかります.次の図を見てください.

2018-08-18_23h30_55

ベクトル\vec{a}に垂直な平面があるとします.この平面に関して,ベクトル\vec{a}と同じ側にあるベクトルは,ベクトル\vec{a}との内積が正の値になります.逆に反対の方向を向いているときは負の値になります.たとえば,ある表面に対してその法線ベクトルと視線ベクトルの内積をとることで,その表面が見えるかどうかがわかります.

ベクトル方向の長さを測る

ベクトル\vec{a}と単位ベクトル\vec{e}の内積を取ると,ベクトル\vec{a}を単位ベクトル\vec{e}の方向で測った値になります.

2018-08-18_23h31_00

式で表すと

\vec{a}\cdot\vec{e} = |\vec{a}|\cos\theta

たとえばXYZの正規直交基底ベクトルを使って,それぞれの軸で内積をとると,各軸の値を求められます.いま,ベクトル\vec{p}が(4,2,-3)の座標を指していた場合

\begin{aligned} \vec{p}\cdot\vec{e}_x &= \begin{pmatrix}4\\2\\-3\end{pmatrix}\begin{pmatrix}1&0&0\end{pmatrix} = 4 \\ \vec{p}\cdot\vec{e}_y &= \begin{pmatrix}4\\2\\-3\end{pmatrix}\begin{pmatrix}0&1&0\end{pmatrix} = 2 \\ \vec{p}\cdot\vec{e}_z &= \begin{pmatrix}4\\2\\-3\end{pmatrix}\begin{pmatrix}0&0&1\end{pmatrix} = -3 \end{aligned}

となります.

ランバートの余弦則

ある表面に入射してくる光の量は,その表面の法線方向と入射方向の余弦に比例します.これを ランバートの余弦則 といいます.表面の単位面積あたりの入射光の強度は,表面の法線方向と光源ベクトル(表面から光源への方向)が同じほど大きくなります.逆に方向が離れるほど入射した光が照らす面積が大きくなり,単位面積あたりの光の強度が小さくなります.この光の強度は内積を使って求められます.法線ベクトルと光源ベクトルの内積を単位面積あたりの強度にかけてあげれば,照度を求めることができます.

衝突判定

内積は衝突判定でかなり活躍します.ノルムは平方根の計算が入りますが,内積なら長さの2乗が求まりますので,2乗のまま使う場合があります.平方根の処理はなるべく回避することで処理速度が速くなりますから.あと,ベクトルへの射影に内積が使われます.

📌 外積の特性

座標系の決定

直交する3軸のうち,2つの基底ベクトルがわかっていれば,それらの外積をとることで残りの1軸を決めることができます.たとえば,進行方向(Z)と天井方向(Y)がわかれば左右方向(X)がわかります.

法線の決定

あるポリゴンの法線は,ポリゴンの2辺から外積を使って求められます.また,法線と接線から従法線を求めるときも外積を使います.

衝突判定

外積も衝突判定に使われます.たとえば分離軸判定によく使われます.

📌 最後に

線形代数の中でベクトルに関して書いてみましたがいかがだったでしょうか.行列や行列式もまとめようと思っていたのですが,時間かかりそうなので一旦ここまでにしました.いずれ,行列や行列式など扱っていこうと思います.
これから線形代数を始める方は入門として,すでに線形代数を学習されているかたは復習やちょっと忘れてしまったという人などが参考になれば幸いです.

📌 参考文献

  • 村上雅人「なるほど線形代数」海鳴社,2001
  • Eric Lengyel著,狩野智英訳「ゲームプログラミングのための3Dグラフィックス数学」ボーンデジタル社,2006