ActionScript 3.0 for 3D □Math03 行列と座標変換
数値をテーブルのように縦横に並べたものが行列です。並べた数値は、一定の決まりにしたがってまとめて計算できます。つまり、行列は同じような計算を大量に行いたいときに使うと便利です。 私たちになじみ深い例は、フィルタでしょう。フィルタは予め決められたカラー演算を、画像のすべてのピクセルに対して適用します。また、2次元あるいは3次元空間における拡大・縮小や回転、移動といった座標変換も、行列の演算で表すことができます。本章では、おもに座標変換を扱う行列の基礎についてご説明します。
[*筆者用参考] 行列の数学「行列のスカラ倍と乗算」。 ○Math03-01 行列とは 行列のなかの数値ひとつひとつを、行列の「成分」または「要素」と呼びます。成分は行と列で特定され、変数で示すときには行と列の番号をその順番で添字にします。ひとつの行列は、成分すべてを括弧()または[]で括ります。 行列の大きさは、行×列で表します。上記の行列は、先頭から順に2×2行列、3×2行列、1×2行列、3×1行列です。行と列の数が等しい行列は、「正方行列」と呼ばれます。そのとき、行列数を次数として、たとえば上記第1番目の2×2行列は、2次正方行列と書表わすこともあります。 また、1行(上記第3番目)あるいは1列(上記第4番目)の行列は、ベクトルを行列として表したものと捉えられます。したがって、それぞれ行(横)ベクトルとか列(縦)ベクトルと呼ばれたりします。ActionScriptの座標変換では、列ベクトルが用いられます。 座標変換を扱うときにもっともよく使われるのは、正方行列と列ベクトルです。行列は、連立1次方程式を解くために考え出されました。連立方程式も、正方行列と列ベクトルを使って表せます。たとえば、つぎの2元連立1次方程式を考えてみましょう。xyが変数、abcdは係数で、pqは定数です。 ax + by = p この連立1次方程式を行列で表すために、まず2次正方行列Aおよび2次元列ベクトルXとPを、つぎのように定めます。 , , 行列は、ベクトルの拡張と捉えることもできます。ただし、ベクトルとひとつ大きく異なるのは、乗算が定められていることです(行列の計算については、次節以降に詳しく説明します)。上記2元連立1次方程式は、正方行列Aと列ベクトルXとの積AXを用いてつぎのように表せます。 AX = P この連立1次方程式を解くというのは、列ベクトルXを求めることです。後でご説明するように、正方行列には逆行列というものが定められています。正方行列Aの逆行列はA-1と表し、上記の式から列ベクトルXがつぎのように導かれます。 X = A-1P 具体的な計算はさておき、連立1次方程式とその解がとても簡単な行列の式になることにご注目ください。実数aについてa-1というのは、aの逆数つまり1/aです。したがって、行列を使うと連立1次方程式が、あたかもつぎのような変数xの単純な1次方程式のように書表わせるのです。 ax = pのとき、x = p/a = a-1p (xとa、pはいずれも実数。ただし、a≠0とする) しかも、連立1次方程式の変数の数はふたつと決まっていません。xyzの3変数になったら、正方行列と列ベクトルの次数をひとつ増やせばいいだけです。それでも、AX = Pという行列の式はまったく変わりません。 もっとも、式が簡単に書けることは、計算が楽になることを意味しません。行列の成分の数はもとの連立1次方程式の変数と係数および定数の数と変わらない訳ですから、計算の手間はほぼ同じといえます。筆者が高校の数学で行列を習ったときも、計算が面倒なので嫌いでした。 しかし、行列のよいところは、手間さえ惜しまなければ求める結果が機械的に計算できることです。授業では筆算させられましたが、今私たちの前には大量の機械的な計算を文句もいわずやってくれるコンピュータがあります。行列演算は、まさにコンピュータにうってつけの処理です。私たちは、ただ行列の成分を定め、計算式を立てるだけでよいのです。
○Math03-02 行列のスカラー倍および和と差 乗じるスカラー値k = 0とすると、行列のすべての成分は0になります。すべての成分が0の行列はゼロ行列と呼ばれ、Oで表されます。 つぎに、ふたつの行列の足し算と引き算を行うには、互いの行と列の数がともに等しくなければなりません(正方行列でなくて構いません)。行列の足し算は、対応する成分をそれぞれ加えます。引き算は逆に、引かれる行列の成分から引く行列の対応する成分をそれぞれ差引きます。
なお、ふたつのm×n行列の行と列の数が等しく、かつ対応する成分(つまり行列Aの成分amnと行列Bの成分bmn)すべてが等しいとき、ふたつの行列は等しいといいます。たとえば、以下のようにふたつの2次正方行列が等しいとすると、a11 = b11かつa12 = b12かつa21 = b21かつa22 = b22となります。 行列の演算は、もちろん一般にm×n行列に対して定義されています。ただ、m×n行列Aをつねに以下のように書くのは煩わしいです。そこで、第i行第j列の成分aijで代表させて、A = [aij]と表します。行列のスカラー倍と足し算・引き算およびO行列について、シンタックスMath03-001にまとめます。 シンタックスMath03-001■行列のスカラー倍と足し算・引き算およびO行列
○Math03-03 行列の積および単位行列と逆行列 ●行列の積
2次正方行列と2次元列ベクトルとの積は、2次元列ベクトルになります。第1に、掛けられる2次正方行列Aの第1行目の2成分(a, b)と、掛ける列べクトルXの(第1列の)2成分(x, y)とをそれぞれ掛合わせ、その和(ax + by)を結果となる積の列ベクトルの第1行(第1列)目の成分とします(図Math03-001左図)。 第2に、正方行列Aの第2行目の2成分(c, d)と、列べクトルXの(第1列の)2成分(x, y)とをそれぞれ掛合わせ、その和(cx + dy)を結果となる積の列ベクトルの第2行(第1列)目の成分とします(図Math03-001右図)。 図Math03-001■2次正方行列と2次元列ベクトルとの乗算
掛けられる正方行列の各行の成分に対して、掛ける列ベクトルの成分をそれぞれ掛合わせて足し、結果となる積の列ベクトルの各行の成分としています。いわば横(行)と縦(列)の成分を掛け算して足し合わせる操作で、ややこしく感じるかもしれません。しかし、このような演算の決まりにしておく方が、変換を繰返す処理を考えたときに都合がよいのです。 ところで、今見たとおり加減算と異なり、乗算ではふたつの行列の大きさ(行列数)が同じでなくても構いません。けれども、掛け算ができるための条件はあります。乗じる行列の行と乗じられる行列の列の成分をそれぞれ掛合わせるには、掛けられる行列の列数と掛ける行列の行数が等しくなければなりません。 2次正方行列の列数は2で、2次元列ベクトルの行数も2ですので、ふたつの積を求めることはできます(図Math03-002左図)。しかし、掛合わせる順序を入替えると、列ベクトルの列数は1で2次正方行列の行数は2ですので、掛け算ができなくなります(Math03-002右図)。つまり、行列の乗算は交換法則が成立ちません。 図Math03-002■掛けられる行列の列数と掛ける行列の行数は等しくなければならない
つぎは、正方行列同士の乗算です。正方行列は行と列の数が同じですから、もちろん掛け算できます。そして、その積は、同じ次数の正方行列になります。つまり、正方行列は、いくつでも掛合わせられるということです。 また、ふたつの正方行列は、掛ける順序を変えて乗算することもできます。しかし、積の行列の成分は、掛ける順序が変われば値も変わります。行列は一般に交換法則が成立たないことにご注意ください。 AB≠BA (AとBは正方行列とする) いくつでも掛けられて、順序を変えると結果が変わるというと、フィルタが想い起こされるでしょう。フィルタのこの性質は、行列の乗算から受継いでいるのです(Tips 03-001「行列の乗算は順序によって結果が変わる」参照)。 具体的に、ふたつの2次正方行列同士の積は、つぎのように求められます。
この計算は、後の掛合わせる正方行列を列に分けるとわかりやすいでしょう。まず、後の行列の第1列目を列べクトルと考えて、前の正方行列に乗じます。その掛合わせた結果が、積の行列の第1列目になります。
つぎは、後の行列の第2列目を同じように列べクトルと見て、前の正方行列に乗じます。その掛合わせた結果を、今度は積の行列の第2列目とするのです。
もっと分解してみましょう。さらに、前の掛けられる正方行列を行に分けます。すると、行ベクトルと列ベクトルの乗算と見ることができます。行ベクトルと列べクトルは、次数が同じであれば掛け算できます(ただし、順序が変わると計算できません)。前の掛けられる行列の第1行目と後の掛ける行列の第1列目を乗算した結果は、積の行列の第1行1列目の成分となります。
この計算に見覚えはないでしょうか。ベクトルの内積です。ふたつのベクトルA1(a11, a12)とB1(b11, b21)の内積は、つぎのとおりでした。 A1・B1 = a11b11 + a12b21 この結果は、積の行列の第1行1列目の成分と同じです。残りの成分の計算もすべて、つぎのように掛けられる行列Aの行と掛ける行列Bの列との内積になっているのです。
それでは、一般のm×n行列A = [aij]とn×l行列B = [bij]との積ABをC = [cij]として、その成分cijを求めましょう。具体的な成分の計算を、徐々に一般化します。まず、Cの第1行1列目の成分c11は、つぎのAの第1行目とBの第1列目の内積です(Maniac! Math02-004「n次元ベクトルの内積」参照)。 c11 = a11b11 + a12b21 + … + a1nbn1 これを少し一般化して、Cの第1列目の各成分ci1として考えると、Aの各行i(1〜m)とBの第1列目の内積になります。 ci1 = ai1b11 + ai2b21 + … + ainbn1 そして、Cの第j列目の各成分cijは、Aの各行iとBの第j列目の内積ですので、つぎの式が導かれます。これが行列AとBの積AB = Cの第i行j列目の成分cijです。 cij = ai1b1j + ai2b2j + … + ainbnj ●単位行列
行列に単位行列を左から掛けても右から掛けても、もとの行列の成分は変わりません(もちろん、左の行列の列数と右の行列の行数は等しくなければ乗算できません)。つまり、任意の正方行列Aについて、つぎの式が成立ちます。 AE = A 実数aに対する1と似た性質をもっているということです。 a×1 = 1×a = a ●逆行列 AA-1 = A-1A = E これは、実数aで考えれば、その逆数1/a = a-1に当たります。 a×a-1 = a-1×a = a/a = 1 正方行列Aと列ベクトルXの積AX = X'が得られたとき、逆に列ベクトルX'からXを求めるのが逆行列A-1になります(Tips Math03-005「逆行列の乗算はいわば割り算」参照)。 X = A-1X' これは2次正方行列で考えるなら、前述Tips Math03-002「2元連立1次方程式の解」を求める計算にほかなりません。2次正方行列Aおよび2次元列ベクトルXとX'をつぎのように定めます。
ここでAX = X'とすると、それはつぎの連立方程式を意味します。 ax + by = x' すると、前述Tips Math03-002「2元連立1次方程式の解」のとおり、xyはつぎの式で求められます。ただし、ad - bc≠0とします。 x = (x'd - y'b)/(ad - bc), y = (ay' - cx')/(ad - bc)これらの式を改めて、列ベクトルXとX'および行列を使って表します。
したがって、2次正方行列Aの逆行列A-1は、つぎのとおりです。
正方行列には「行列式」というスカラー値が定められます。正方行列Aの行列式は、|A|またはdet(A)で表します。そして、上記の2次正方行列Aの行列式|A|は、つぎの式で求められます。 上記2次正方行列Aの逆行列A-1は、Aの行列式|A|を使ってつぎのように表すこともできます。また、逆行列が存在するためには、|A|≠0でなければなりません(Tips Math03-006「得られた逆行列が定義を満たすことの確認」参照)。
●行列の積と単位行列・逆行列の定義や性質
Σの下のk = 1がkの初項の値です。つまり、1から始めて、kを1ずつ増やしながら加え、Σの上に記した100までの和をとるという意味です。
行列の積や単位行列と逆行列について、それらの定義および計算の性質をシンタックスMath03-002にまとめました。できるだけ行列数をかぎらない一般的なかたちで示してあります。しかし、単位行列や逆行列のように正方行列を前提とするものもあります。また、逆行列は次数が増えると複雑になるので、2次正方行列の結果のみを説明しました。 シンタックスMath03-002■行列の積と単位行列・逆行列の定義および性質
○Math03-04 伸縮と回転の座標変換を行う行列 ●行列による位置ベクトルの変換
これらの行列についてつぎの式が成立つとします。そして、ふたつの列べクトルXとX'は、2次元平面の位置ベクトルを表すものと捉えます。 AX = X' すると、位置ベクトルXの表す座標(x, y)が、2次平方行列Aにより位置ベクトルX'の座標(x', y')に変換されたと見ることができます。
そのように捉えれば、2次正方行列Aの逆行列A-1が存在するとき、A-1は行列Aによって変換された位置ベクトルX'をもとの位置ベクトルXに戻す変換になります。 A-1X' = X また、単位行列Eによる変換は、掛合わせた列べクトルXの成分を変えません。つまり、座標はそのままということです。 EX = X ●伸縮の変換
列べクトルをスカラー倍すると、原点からの位置ベクトルの座標値がその比率にしたがって伸縮します。たとえば、矩形の4角の位置ベクトルを2倍すれば、その各座標値が2倍になり、矩形の1辺もそれに合わせて2倍に拡大します(面積は1辺の2乗で4倍になります)。 下図Math03-003は、正方形の4角の座標をそれぞれ(20, 70)、(70, 70)、(70, 20)、(20, 20)として、位置ベクトルを2倍にしました。拡大された正方形の座標値は、それぞれ(40, 140)、(140, 140)、(140, 40)、(40, 40)になります。各座標の原点からの距離とともに、1辺の長さも50(= 70 - 20)から100(= 140 - 40)と2倍になります。 図Math03-003■原点を中心に位置ベクトルがスカラー倍になる
乗じる2次正方行列の対角成分ふたつを異なった値にすると、x軸方向とy軸方向とで位置ベクトルを伸縮する比率が変わります。
たとえば、前掲図Math03-003と同じ正方形の4角の位置ベクトル(20, 70)、(70, 70)、(70, 20)、(20, 20)に第1行1列目成分が2で第2行2列目成分1.5の2次正方行列を左から乗じると、それぞれの位置ベクトルは下図Math03-004のようにx軸方向が2倍でy軸方向は1.5倍に伸びます。スカラー倍とは異なり、変換された位置ベクトルはもとのベクトルとは方向が変わります。 図Math03-004■位置ベクトルのxy座標に異なった比率を乗じる
つぎに、3次元空間における位置ベクトルの伸縮を考えてみましょう。位置ベクトルが3次元になりますので、乗じるのは3次正方行列とします。そして、位置ベクトルのz座標と掛合わされる対角成分に、伸縮の比率を設定します。
位置ベクトルを2次元平面と3次元空間とでそれぞれ伸縮する正方行列を、つぎのシンタックスMath03-003にまとめました。 シンタックスMath03-003■伸縮の行列
●回転の変換 x' = x cosθ - y sinθ この式を2次正方行列と2次元の列ベクトルで示すと、つぎのようになります。この回転を表す正方行列は、「回転行列」と呼ばれます。
つぎに、3次元空間における回転は、予め何らかのかたちで中心軸を定めます。本章では、基本となるxyzの各軸による回転を考えましょう(Tips Math03-009「任意の軸による回転」参照)。
上記の2次元平面における回転は、3次元空間で見れば、z軸を中心に回していることになります。つまり、z座標は変えることなく、xy平面で位置ベクトルを回転します。z軸による3次元空間の回転行列は、以下のとおりです。2次元平面における回転行列に、第3行目と第3列目が加わっています。これらは、z座標の値が変わらず、またその値がxy座標値に影響を与えないように定められています。
列べクトルの成分を変えない正方行列とは、単位行列のことでした。つまり、上記のz軸による3次元空間の回転行列は、3次単位行列に2次元平面の回転行列を組込んだものと捉えることもできます。
そう考えると、他の軸による回転行列も簡単に求められます。2次元平面の回転行列を、1行下かつ1列右にずらして、3次単位行列に組込めば、x座標値は変えずに(y, z)座標を角度θ回す、つぎのようなx軸による3次元空間の回転行列になります。
上記のx軸による回転行列から、さらに1行1列ずつ2次元平面の回転行列の成分を3次単位行列のうえでずらせば、残るy軸の回転行列が得られます。もっとも、下の行と右の行が3次単位行列の外にはみ出てしまいます。これらは、つぎのように第1行目と第1列目にいわばスクロールさせます。
このようにして得られた3次正方行列が、y軸で(z, x)座標を角度θ回す3次元空間の回転行列となります。
2次元平面の原点を中心とした回転行列と3次元空間におけるxyzの各座標軸で回す回転行列を、つぎのシンタックスMath03-004にまとめました。 シンタックスMath03-004■回転行列
○Math03-05 線形変換とアフィン変換 ●線形変換(一次変換) RSX = X' 行列の乗算には、交換法則が成立ちませんでした(シンタックスMath03-002)。したがって、列べクトルXを回転Rしてから伸縮Sした以下の列べクトルX"は、上記の列ベクトルX'とは必ずしも同じになりません。 SRX = X" なお、掛合わせる列ベクトルに近い正方行列の変換から順に行われます。つまり、列べクトルXについて、これを伸縮Sしてから回転RしたのがベクトルX'です。逆に、回転Rしてから伸縮Sすると、ベクトルX"になります。もっとも、乗算の順序を変えなければ、計算は前からやっても、後からやっても積は同じです(シンタックスMath03-002)。 (RS)X = R(SX) = X' よって、ふたつの正方行列RとSの積の正方行列をA = RSとし、列べクトルXを伸縮Sした変換後のベクトルがP = SXだとすれば、上記の式はつぎのように書替えることもできます。つまり、ふたつの正方行列の積Aを予め求めて列べクトルXと乗じても、隣の正方行列Sの変換を加えた後の列べクトルPにつぎの正方行列Rを掛合わせても、変換の結果X'は変わらないということです。 RSX = AX = RP = X' 座標変換を組合わせると、Flashの[自由変形ツール]のように位置ベクトルの座標を変えることができます(図Math03-005)。このような座標変換を「線形変換」または「一次変換」といいます。ただし、線形変換では、原点は動かせません。[自由変形ツール]でいえば、変形点が基準点に固定されているような状態です。 図Math03-005■[自由変形ツール]で座標を動かす
線形変換の幾何学的な性質としては、3つ挙げられます。第1に、上述のとおり原点は動きません。つまり、座標変換は原点を中心に行われます。第2に、直線は変換した後も直線です。第3に、平行な直線をともに変換すると、変換後もやはり平行が保たれます。
[*筆者用参考]「行列 : 数学」、『プログラミングのための線形代数』p.26。 線形変換は、数学では抽象的に関数または写像として、以下のシンタックスMath03-005のように定められます。数学の「関数」とは、ひとつの値に対して、ただひとつの値を定める決まりのことです(Word Math03-003「関数」参照)。値xにyを対応させる関数fは、つぎのように表されます。 y = f(x) 線形変換では値はベクトルですので、ActionScriptのつぎのような関数f()をイメージすればよいでしょう。この関数f()の戻り値が、yに当たります。 function f(x:Vector3D):Vector3D 関数をさらに抽象化して定義したのが「写像」です(Word Math03-004「写像」参照)。つまり、関数は写像のひとつです。 シンタックスMath03-005■線形変換(一次変換)
これまで述べた行列による座標変換は、変換するための正方行列をA、変換される列べクトルはXで示すと、つぎのような関数(写像)fとして表すことができます。 f(X) = AX すると、シンタックスMath03-002に述べた「行列の積」の演算法則により、線形変換のふたつの性質を満たすことが確かめられます。任意のふたつのベクトルをXおよびYとし、任意のスカラーをkとします。
したがって、この座標変換は線形変換です。
●アフィン変換
これで、2次正方行列で2次元列ベクトルを変換した座標(ax + by, bx + dy)に、移動分のxy座標(tx, ty)が加わりました。けれども、2×3行列では、複数の変換を乗算で合成することができません。 そこで、変換の行列に第3行目を加えて、3次正方行列にします。加えた成分が変換に余分な影響を与えないように、3次単位行列の第3行目を組込んでシンタックスMath03-006のように定めます。これで、複数の正方行列を乗じて変換が合成できます。また、変換した後の列ベクトルの第3行(第1列)目成分は、つねに1となります。3次元空間のアフィン変換も、同じように定められます。 シンタックスMath03-006■アフィン変換
アフィン変換であれば、任意の点を中心に座標を変換できます。その任意の中心点を原点Oに平行移動する変換が正方行列T、加えたい変換は正方行列Aだとすれば、列べクトルXに対してつぎのような乗算を行えばよいからです。 T-1ATX この変換は、列ベクトルXを行列Tにより中心点が原点Oに重なるよう平行移動した後、中心点と一致した原点で行列Aの変換を行ったうえ、Tの逆行列T-1で中心点をもとの位置に戻すことになります。なお、アフィン変換でも、線形変換と同じつぎのふたつの幾何学的な性質は保たれます。
●転置行列
それだけでなく、列べクトルと乗じた正方行列と比べて、行と列の成分が入替わっていることにご注意ください(上の式と下の式の正方行列は、成分のbとcが入替わっています)。考えてみると、列ベクトルの行と列の成分を入替えれば、行ベクトルになります。
行列Aの行と列の成分を入替えた行列は「転置行列」と呼び、ATで表します。すると、上記ふたつの式の行列には、つぎのような関係が成立っています。
正方行列と列べクトルとの積AX = X'とすると、両辺を転置すれば(AX)T = X'Tです。そして、シンタックスMath03-007に示すとおり、(AX)T = XTATとなります。したがって、つぎの等式が成立つのです。 XTAT = X'T つまり、行ベクトルに正方行列を乗じた座標変換も、正方行列と列ベクトルの積と同じ内容の変換を表します。ただし、そうした解説を読むときには、行と列の成分が入替わっていることに注意しなければなりません。 シンタックスMath03-007■転置行列
作成者: 野中文雄 Copyright © 2001-2010 Fumio Nonaka. All rights reserved. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||