タートルグラフィックス
Mathematicaパッケージの使い方として、タートルグラフィックスを取り上げよう。
筆者で作成したタートルグラフィックスのためのMathematicaパッケージ Turtle.zipを展開し Turtle.m をMathematica内で次のコマンドで返るフォルダ場所(なければ作成する)に置く。
FileNameJoin[{$UserBaseDirectory, "Applications"}]
MacOSなら次のようになる:"/Users/username/Library/Mathematica/Applications"
Mathematicaからパッケージ Turtle.m を読み込むには、Mathematica Notebook の冒頭で次のように書いて実行する(記号 (`) はバッククォート backquote である)。
<< Turtle`
このMathematicaパッケージで利用できる関数は次のようである。必要なら Turtle.m に関数を追加すればよい。
| initializeTurtle[start] | 引数リストstart({x,y})で指定した位置に亀をセット。引数省力時には {0,0} をデフォルトに。 |
|---|---|
| setTurtleDirection[angle] | 亀の向きを angle(radian) にセット。省略時は 0 |
| rightTurn[a] | 現在の亀の向きを右に a(radian)回転 |
| leftTurn[a] | 現在の亀の向きを左に a(radian)回転 |
| forwardTurtle[s] | 現在の亀の方向に s だけ前進 |
| backwardTurtle[s] | 現在の亀の方向に s だけ後退 |
| showTurtlePath | 亀の軌跡を線で描く(引数なし)。位置のリストをLineでつなぐ) |
| getTurtlePath | 亀の位置リストを返す(引数なし) |
| getTurtlePosition | 亀の現在位置を返す(引数なし) |
| getTurtleDirection | 亀の現在方向(radian)を返す(引数なし) |
Koch曲線を描く
右図は以下のMathematicaコードで描いたタートルグラフィックによるKoch曲線である。
(* パッケージ Turtle の読み込み *)
<< Turtle`
(* Koch曲線のTurtle的定義: length 両端の距離、Koch曲線のフラクタル的深さ *)
kochCurve[length_, 0] := forwardTurtle[length];
kochCurve[length_, depth_] := Module[{},
kochCurve[length/3, depth - 1];
leftTurn[Pi/3];
kochCurve[length/3, depth - 1];
rightTurn[2 Pi/3];
kochCurve[length/3, depth - 1];
leftTurn[Pi/3];
kochCurve[length/3, depth - 1]
]
(* Koch curveを描く手順 *)
initializeTurtle[]; (* 亀の初期化 *)
kochCurve[1, 4]; (* 長さ1 深さ4のKochポイントを求める *)
getTurtlePath[] (* 必要ならKochポイントのリストを表示 *)
showTurtlePath (* Koch曲線を描く *)
(* Koch Curve を描く関数 *)
showKochCurve[n_] := Module[{},
initializeTurtle[];
kochCurve[1, n];
showTurtlePath
]
showKochCurve[3]
Paper folding曲線(dragon曲線)を描く
右図のPaperfolding曲線(Dragon曲線)をタートルグラフィックスで描いてみよう。 foldingの仕方から明らかであるが、右図で$\frac{\pi}{2}$で交わる骨格部を表す2部分は前回のfoldingで得られた曲線が真ん中でつながっている。 この意味でPaperfolding曲線は自己相似形である。
再帰的亀で描く
Paperfolding曲線の成り立ちを観察するとわかるように、 $n$回折れたたんだPaperfoloding曲線の折れ曲がり角点列を両端点間を長さ length 間で得る paperfolding_dragon[length, n] を考えてみよう()。
左図のようにして直線をそれを底辺とする直角三角形をなす2本の直線で再帰的に置き換えていく。 このとき、置き換える直角三角形(の辺)が直線の進行方向に左右交互に45度回転するように工夫することがポイントである。 そのために、折り畳み点列を返す関数として paperFoldingDragon[length, depth, parity] のように1,-1を取るparity変数を引数に加えて定義すればよい。 最後に、「左に parity $\cdot \frac{\pi}{4}$ 回転しておく」も必要なことも理解しよう(この操作をしないとどうなるかを試してみよう)。
paperFoldingDragon[length_, 0, parity_] := forwardTurtle[length];
paperFoldingDragon[length_, depth_, parity_] := Module[{},
leftTurn[parity Pi/4];
paperFoldingDragon[length/Sqrt[2], depth - 1, 1];
rightTurn[parity Pi/2];
paperFoldingDragon[length/Sqrt[2], depth - 1, -1];
leftTurn[parity Pi/4];
]
showPaperFoldingDragon[depth_] := Module[{},
initializeTurtle[];
paperFoldingDragon[1, depth, 1];
showTurtlePath
]
紙折り列にしたがって歩く亀で描く
紙折り列と紙折り曲線にあるように、紙を2つ折り操作を $n$ 回繰り返して得られる記号 d と u からなる2-folding列を求めておく(記号 d と u の亀の向き変化は、上の図に合わせるために逆になる)。
初期化 initializeTurtle[] された亀の方向は 0度方向を向いている。 原点{0,0}から位置{1,0}まで forwardTurtle[1.0] で歩いた亀は、2-folding列 foldstring を読みながら次のように向きを変える。
- 記号 d に出会うと、向きを右に90度回転 rightTurn[Pi/2]
- 記号 u に出会うと、向きを左に90度回転 leftTurn[Pi/2]
kame.forward(1.0)
for i in range(0, len(foldstring)):
if foldstring[i] == 'd':
kame.right(Pi/2)
elif foldstring[i] == 'u':
kame.left(Pi/2)
kame.forward(1.0)