youtubeで見かけたPGAのチュートリアルを見て感動しました。3次元の座標系を計算するとき、手を動かすには複雑な概念がわさわさ出てきて嫌な気持ちになりますよね。それらが全部おなじ基底であつかえるとなると俄然楽しそうです。動画を参考にPGAの概要を紹介します。
PGAの基底は平面から始まる
初めにすべての3次元平面
(ax+by+cz+d=0)を表す基底を考えます。
ex=(x=0), ey=(y=0), ez=(z=0), eo=(const=0) ex,ey,ez,eoの4本の基底の線形結合で任意の平面を表すことができます。
aex+bey+cez+deo=(ax+by+cz+d=0) PGAのMeetで共通部分が求まる
PGAの演算にはいくつか種類があります。その中の1つがMeetです。Meetは基底を次のルールで計算します。
ea∧ea=0ea∧eb=eaeb 同じ基底があれば0。そうでなければ基底を並べて新しい基底にします。
eaeb=eabと略記します。
eab=eaeb=−ebea=−eba 並んだ基底を1箇所入れ替えると符号を反転させます。
Meetが賢いのは、これだけで平面の共通部分である直線を計算できることです。
(x+y−1=0)と
(z−1=0)の共通部分を求めてみましょう
(ex+ey−eo)∧(ez−eo)=ex∧ez−ex∧eo+ey∧ez−ey∧eo−eo∧ez+eo∧eo=exz−exo+eyz−eyo−eoz+0=−ezx+eox+eyz+eoy−eoz なんだかあまり見慣れない形になりましたが、これが直線の表現らしいです。そもそも三次元の直線の表現ってなんだと思いましたが、どうやらPlücker座標というらしいです。
3次元の直線は向きのベクトル
dと直積のベクトル
mで表現できます。
Plücker座標が次のように展開されています。
dxeyz+dyezx+dzexy+mxeox+myeoy+mzeoz 先程の共通部分では次のようになります。
d=(1,−1,0) m=(1,1,−1) 点A(1, 0, 1)から点B(0, 1, 1)への直線なので、
d=A−B, m=A×Bを満たしてますね!すごいです!
Meetでもっと共通部分が求まる
Meetは平面と平面の共通部分だけではありません。直線と平面の共通部分も求められます。先程の直線と平面
(x−2=0)の共通部分も求めてみましょう。
(−ezx+eox+eyz+eoy−eoz)∧(ex−2eo)=eyzx+eoyx−eozx+2ezxo−2eyzo=2eozy−eoxz+eoyx+exyz ∧の両側に同じ基底があるともりもり消えます。計算された点のPGAでの表現は次のようになります。
xeozy+yeoxz+zeoyx+wexyz ただし、wが1でないときは全体をwで割って正規化する必要があります。
直線と平面の共通部分の計算結果は点(2, -1, 1)になりました。
(x+y−1=0)と
(z−1=0)と
(x−2=0)をすべて満たすので間違いないですね!平面
∧平面
∧平面で点が求まるのはとても美しいです。
Joinでつながる点と点
ここまでは共通部分を求める演算でしたが、逆につなげる演算もできます。Meetに対して双対なJoinという演算を考えます。Joinのために、基底を反転する演算を考えます。
!exz=eoy 詳細を省きますが、↑みたいな感じです。Joinは次のように定義できます。
a∨b=!(!a∧!b) これを使うと点と点をつなぐことができます。A(1,0,1) B(0,1,1)を繋いでみましょう。
(eozy+eoyx+exyz)∨(eoxz+eoyx+exyz)=−ezx+eox+eyz+eoy−eoz さっきと同じ直線の表現が無事得られました。ここまで来たら同様に平面までつなげることができます。偉いですね。
回転とか変換とか
ここまでは三次元のモノどうしの関係を扱いました。実は回転や変換などもここまでの基底で表すことができます。詳細を省きますが、直線
l(軸
d)に対する回転子
mは次のようになります。
m=cos2θ+sin2θld 回転子
mを使って点
pを回転させるには両側から挟んで積を取ります。
p′=mpm 長くなってきたので、PGAの積や
mについては次のページを参照してください。チートシートや計算機もあり非常に便利なサイトです。
つまり、3次元回転でおなじみのクオータニオンもPGAの中に含まれています。いたせりつくせりです。16個の基底を簡単にこねくり回すだけで、これだけの表現ができるので感動します。
ちなみに、
Rustの実装も存在します。使ってみたいですね。
おまけ
ここまでの知識で螺旋をくるくるするコードを書いてみました。行列のことを知らないで実装するのは不思議で楽しいですね。
メモ: クリフォード代数だと平面を基底にするのではなく、点を基底にして始めるほうが普通らしい?