プログラミングで遊ぶ:フラクタル編

フラクタルは自己相似図形と呼ばれ、図形の一部を拡大すると、再び同様の図形が現れるものをいいます。簡単な数式から美しいフラクタル画像が生成されます。今回は、p5.js という描画用言語を利用して、フラクタルの世界を探検します。

1.p5.js の利用

p5.js のウェブエディタ(https://alpha.editor.p5js.org/)にアクセスして利用します。(右図)
  1. 図左のエディタ欄にプログラムを入力し()で実行すると、結果が右の Preview 欄に表示されます
  2. draw()関数はデフォルトで毎秒60回実行され、()で停止します
  3. プロジェクト名は、最初自動的につきますがクリックして変更できます
  4. ユーザ登録しなくても使えますが、プログラムの保存(読込)ができないので、以下の手順で登録を行います

利用登録【Sign Up】

  1. 利用に際し、次の情報をあらかじめ決めておきます
    User Nameニックネームでかまいません
    EmailEmailアドレス
    Password忘れないものを
  2. ウェブエディタ画面右上の Sign up をクリックすると、右の画面になります
  3. 1.の情報を入力(Confirm Password欄には確認のためパスワードを再入力)し Sign Up をクリックします
  4. 現れた画面の右上に Hello ユーザ名! と表示されればO.K.です

再利用【Log In】

  1. ウェブエディタ画面右上の Log In をクリックすると、右の画面になります
  2. 利用登録時に入力した情報、「Emailアドレス又は User Name」と「パスワード」を入力し Log In をクリックします
  3. 現れた画面の右上に Hello ユーザ名! と表示されればO.K.です

2.最初の p5.js プログラム

 リサジュー図形はフラクタルではありませんが、p5.js の簡単な入門を兼ねて、作成します。
 このプログラム は $(\cos(nt),\,\sin(mt+d))$($0\leqq t\leqq 360^\circ$)で媒介変数表示されるリサジュー図形を描きます。プログラムを自分のp5.jsウェブエディタにコピーし、パラメータ $n,\,m,\,d$ の値を変えながら実行させてみましょう。
 アニメーション版 はdraw()関数を利用して、描画過程をアニメーション表示します。

【補足】自分でプログラミングしてみようという方へ(p5.jsレファレンス
このプログラムは、子供のころよく遊んだスピログラフ®を描きます。パラメータを色々変えて楽しんでください。

3.マンデルブロ集合

 マンデルブロ集合は、フラクタルの概念を提唱したマンデルブロが定義しました。点($x,y$)を
  $(x,y)\mapsto (x^2-y^2+c_x,2xy+c_y)$ の計算を繰返して
  発散する(原点から2以上離れる)までの計算回数(発散速度)
で色付けします。このとき定数部を$(c_x,c_y)=(x,y)$(出発点)とするのがマンデルブロ集合で、想像もできない程複雑で美しいフラクタル画像が現れます。
 例えば $(0.5,0.5)\mapsto(0.5,1)\mapsto(-0.25,1.5)\mapsto(-1.6875,-0.25)\mapsto(3.285,1.344)$ ですから、($0.5,0.5$) から出発した点は $4$回で発散します。右の全体図で黒い領域は発散速度$\;0\;$で、外側に赤紫の高発散速度領域が広がっています。緑や赤い点で彩られた境界領域が複雑な振舞をする(少しずれると発散速度が著しく異なる)領域で、宝物がたくさん隠れています。
 p5.jsプログラムで描画領域の中心($x_0,y_0$)とサイズ$\;s$、最大計算回数 $maxIt$、色調 $R,G,B$ を変えて、宝物をみつけましょう。
 拡大縮小のアニメーションプログラムは、このプログラムを編集可能にしたものです。 mandel.setUniform('p', [-0.74364388703, 0.13182590421]); で設定される中心座標を変えて、探索してみましょう。
 また、このサイトには、美しい画像が得られるパラメータ値やマンデルブロ集合の詳しい情報があり、【マンデルブロ集合描画スクリプト】はとてもよくできています。
【注】$(x,y)\mapsto(x^2-y^2+c_x,2xy+c_y)$ は、複素数計算の $x+yi\to(x+yi)^2+(c_x+c_yi)\;$を意味します。

パラメータ例
全体図:x0=0, y0=0, s=2, maxIt=50,
例1:x0=-0.74364388703, y0=0.13182590421, s=0.005, maxIt=1000,
例2:x0=-1.1929755697967157, y0=-0.16206578744951963, s=0.002, maxIt=1000,
例3:x0=0.3335437395630575, y0=0.42517525749876034, s=0.00002, maxIt=1000,

ジュリア集合は、マンデルブロ集合と同じ計算式ですが、定数部$(c_x,c_y)$を定点とし、同じく複雑で美しい画像が得られます。 このブログラムで、定数部や描画領域をいろいろ変えて楽しんでみましょう。

4.タートルグラフィックス

スクラッチなどの経験がある方にはお馴染みの概念で、描画領域中で亀(Turtle)を歩かせ線画を描きます。p5.jsに亀を追加したプログラムで遊んでみます。
亀 t は、
  1. var t=new Turtle($x,y,d$); 位置($x,y$)に向き$\;d\;$で誕生し
  2. 自分の位置(t.x,t.y)、向き t.dir、色 t.color、太さ t.weight を知っていて
  3. $p\;$歩く:t.walk($p$)、$p\;$飛ぶ:t.jump($p$)、$d^\circ$回る:t.turn($d$) ことができ
  4. 位置:t.setPos($x,y$)、向き:t.setDir($d$)、色:t.color=、太さ:t.weight= の直接設定もできます。

以下の例も、亀の誕生位置・角度(Turtle($x,y,d$))を調整しながら、試してみましょう。
四角形:for (var i=0; i<4; i++) {t.walk(100); t.turn(90);}
星形:for (var i=0; i<5; i++) {t.walk(100); t.turn(144);}

5.L-システム

Lindenmayer により提唱されたシステムで、開始文字列と書換え規則の(全体)適用により成長する文字列を記述します。
例.開始文字列$\;A$、規則 $A\to B,\ B\to BA$ に対する導出(空白は分かり易さのために入れました)は
$A\Rightarrow B\Rightarrow BA\Rightarrow BA\,B\Rightarrow BA\,B\,BA\Rightarrow BA\,B\,BA\,BA\,B\Rightarrow \cdots$
となります。
【補足】文法との違いは、規則を列全体に一斉適用することです。このシステムは、$A\to B\;$を成熟、$B\to BA\;$を細胞分裂(生殖)と解釈すると、一番簡単な細胞(生物)集合の成長モデルになっています。第$\;n\;$ステップで導出される文字列を$\;S(n)\;$とおくと、$S(n+2)=S(n+1)S(n)\;$で、その長さ $|S(n)|\;$はフィボナッチ数列になっています(確認してみて下さい)。自然界にフィボナッチ数列がよく出現する理由かもしれません。

 L-システムは、文字(の一部)をタートルへの指令と解釈することにより、様々な線画を記述できます。Kevin Roast教授のサイトでは多くの実例を楽しめますし、日本語の解説サイトもあります。Prusinkiewicz と Lindenmayer の著書The Algorithmic Beauty of Plantsは現在フリーで入手でき図版を眺めるだけでも楽しいです。

 p5.jsプログラムでは文字を次のように解釈しています。L-システム(開始文字列と規則)と反復回数$\;n$、タートルの開始位置と向き、$step,\ angle$ を適当に設定して楽しんでください。
文字タートル t への指令備考
Ft.walk($step$)$step\;$歩く
ft.jump($step$)$step\;$飛ぶ
+,-t.turn($\pm angle$)$\pm angle^\circ\;$左回転(反時計回り)
1,2,….9t.weight=1,2,….9太さ指定
b,g,y,lt.color='brown','green','yellowgreen','lightgreen'色指定。Roast教授のC0~C3
[stack.push(Object.assign({},t))t(のコピー)をスタックに退避
]t=stack.pop()直前の'['で退避した t を取出し、描画再開
その他無し上記以外は書換え規則用の文字
【補足】

例.星形のパラメータ
  step=100, angle=144,	//'F'の歩数と右'-',左'+'の回転角
  L_str='b2X', n=5, //開始文字列と反復回数
  Rules={'X':'F+X'},
  t=new Turtle(300,300,36), //亀の出発位置と向き

例.ドラゴンカーブのパラメータ
  step=4, angle=90, //'F'の歩数と右'-',左'+'の回転角
  L_str='FX', n=12, //開始文字列と反復回数
  Rules={'X':'X+YF+',
         'Y':'-FX-Y'},
  t=new Turtle(300,200,90),//亀の出発位置と向き