「バーンズリーのシダ」では、「さっぱりわかりません」で終わらせていた以下の生成規則について掘り下げてみたいと思います。
各々、大雑把には以下の様な部分を形成するための数式となっています。
f1〜f4の各数式は、以下の様な形をしています。
2×2行列(a〜d)は回転と拡大・縮小変換、加算項(e,f)は平行移動の、各アフィン変換を実施するパラメータです。
加算項(平行移動、e,f)の影響は自明なので、解析すべきは変換行列(a〜d)の方です。回転や相似変換などの変換行列は以下の様な形をしています。
バーンズリーのシダを生成するための数式f1〜f4で使われている行列(a〜d)は、上の様なアフィン変換の合成だと考えられます。アフィン変換を合成するには、各行列の積を取ります。
例えば、回転(Mr)して→拡大・縮小(Mk)して→シアー変換(Ms)する場合、その変換行列Mt=Ms(Sx,Sy)×Mk(Kx,Ky)×Mr(θ)となります。行列は掛け算の順番で結果が異なるので、演算順番は重要です。
変換順番が、拡大・縮小(Mk)して→シアー変換(Ms)して→回転(Mr)する、だった場合、その変換行列は、Mt’=Mr(θ)×Ms(Sx,Sy)×Mk(Kx,Ky)と、なって、一般にその計算結果は異なります(Mt≠Mt’)。
本ページでは、バーンズリーのシダの変換行列を上例のMtの順番だと仮定して、そこからθ,Kx,Ky,Sx,Syの各パラメータを逆算してみたいと思います。
変換行列は2行×2列なので、変換行列(a〜d)=Mtとおくと、4個の方程式を立てることが出来ます。これに対して未知数はθ,Kx,Ky,Sx,Syの5個と、これでは方程式の数が足りず、解が求まりません。
そこで、シアー変換のSy=0に固定してしまいます。Sy=0に固定しても、恐らく必要な自由度を失わないので、問題ないでしょう。これによって未知数が4個となり、4元4連立方程式が立ちますので、バーンズリーのシダの生成規則からθ,Kx,Ky,Sxのパラメータを逆算することが出来ます。
さてさて、言うは易しですが、まず、4×4行列Mtの計算がしんどいです。その結果立てた4元4連立方程式も、三角関数を含む方程式なので、解くのはそこそこ大変です。
そこで、前節の代数計算をMathematicaと言うソフトウェアにやらせようと思います。Mathematicaや、それを実行するための超小型コンピュータRaspberry Piについては、以下の記事をご参照ください。
Mathematicaで変換行列Mtを計算させた様子は以下の通りです。
これで準備が完了しましたので、MathematicaのSolve[ ]関数を使って、4元4連立方程式を4回解きます(↓)。
※上のSolve[ ]一回で、1つの4元4連列方程式を解いています。「4元4連列方程式を解くためにSolve[ ]を4回実行している」のではありません!Solve[ ]が4回なので、4元4連列方程式を4回解いています。
それぞれ、複数個の解が示されました。どれを使っても同じですが、θ(=th)の絶対値が最小となる解を選んで使用しました。……ちなみに、上の4元4連立方程式×4回を手計算で解くのは御免蒙りますm(1__)m。
意味不明だったバーンズのシダの生成規則(変換行列)を、回転変換、相似変換、シアー変換に分解することが出来ましたので、各々のパラメータがシダの葉の生成にどのように影響を与えるのか?各パラメータを少しづつ変更して見れば、知ることが出来るはずです。
そこで、th,kx,ky,ssのパラメータから、一次変換行列を生成する手続きを作りました(↓)。
procedure bsmat th, kx,ky, ss, mx,my
{
para mx,my,0;
matrix 1, 0, 0, 0,
ss, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
sim kx,ky,1;
rotz th*180/PI;
}
回転変換(rotz命令)と相似変換(sim命令)は、Xi-TRACEの命令を使って実装しました。シアー変換はXi-TRACEの命令ではサポートが無いので、matrix命令を使って等価な変換を実施しています。(mx,my)は、平行移動(para命令)のパラメータです。
上の手続きを使うと、例えば、f2の変換処理は以下の様になります。
====旧(↓)
:
elif (rn<pr1 + pr2)
{
// f2: 左葉
matrix 0.20, -.26, 0, 0.00,
0.23, 0.22, 0, 1.60,
0, 0, 1, 0,
0, 0, 0, 1;
linear nx,ny,nz;
}
:
====新(↓)
:
elif (rn<pr1 + pr2)
{
// f2: 左葉
static : bsmat 0.915101, 0.328024,0.31644 -0.104089, 0,1.60;
linear nx,ny,nz;
}
:
手続きbsmatに、Mathematicaで求めたth=0.915101,kx=0.328024,ky=0.31644,ss=−0.104089及び、平行移動項(0,1.60)を渡して変換行列を生成するように変更しました。
意味不明だった変換行列に、一応理屈が通りました。
ここから先は、地道にパラメータを変更して見て、バーンズリーのシダがどのような形に変形するのか?を解析して行きます。
解析したところ、ざっとこんな所(↑)です。言葉ばかりでわかり難いと思いますので、下に示す動画でシダの葉が変化する様子を確かめてみてください。
完成したデータをリンクしておきます。
Xi-TRACEデータ | barnsley_fern_var.xitr |
データを実行すると、以下の様なアニメーションデータを作成することが出来ます。生成式の変換行列をダイナミックに変化させながら、シダの形がどうなるかを動画にしてあります。
2Dのグラフィックですが、計算には結構な時間がかかりました。Xi-TRACEのデータ(スクリプト)はインタプリタ方式で遅いですし、高解像度でそれなりにシダらしき形状にするためには繰り返し回数NNを大きくとる必要があったためです。さすがに、これでレイトレーシングする気にはなれませんでした(1^^;)。