- トップページ
- 書庫
- Context Free for beginners
- 再帰呼び出しでシェイプを描く
再帰呼び出しでシェイプを描く
Context Freeでは、ルールを再帰呼び出しできます。 再帰呼び出しとは、あるルールの中でそのルール自身を呼び出す事です。 この例を見てください。
startshape Circles
rule Circles {
CIRCLE {}
Circles { x 0.95 s 0.9 r 30 }
}

startshapeがCirclesというルールを呼び出しており、Circlesの中では、円を描画した後で、Circles自身をx軸方向に0.95個分移動させ、スケールを0.9に縮小し、反時計回りに30度回転させて呼び出しています。 呼び出されたCirclesは、円を描画して、Circles自身をx軸方向に0.95個分移動させ、スケールを0.9に縮小し、反時計回りに30度回転させて呼び出し、呼び出されたCirclesは、円を描画して…
このように、自分自身を呼び出すことを再帰呼び出しと言います。 再帰呼び出しが無限ループに陥るのを防止するため、Context Freeはシェイプが描画できないスケールになった時点で処理を終了します。
この例では、Circlesを再帰呼び出しする際に、位置の移動と回転に加えてスケールも変更しました。 これにより、円の大きさがだんだんと小さくなって最後は描画できないスケールになり、Context Freeが再帰呼び出しを終了したのです。
再帰呼び出しを終了させる別の手段として、描画ルールと同じ名前の描画終了ルールを用意して、描画終了ルールがランダムに選ばれた時点で処理を終了させる方法があります。
startshape Circles
rule Circles {
5 * { y -1 } CIRCLE {}
Circles { x 1}
}
rule Circles 0.1 { }
このコードを実行すると、y軸方向に5つの円を描く処理が、x軸方向に移動しながら何回か繰り返されて終了します。
2番目のCirclesにはウエイトとして0.1が指定されているだけで、中カッコ内は空です。 中カッコ内が空ということは、再帰呼び出しをしないということですから、2番目のCirclesが終了ルールとなります。 最初のCirclesのウエイトは省略されているのでデフォルトの1となり、2番目のCirclesのウエイトが0.1ですので、1:0.1の比率で処理続行と終了が選択されます(処理終了確率が高いので、なにも描画されないこともあります)。
これらを応用して、木のようなイメージを描画してみましょう。
startshape Tree
rule Tree 0.6 {
SQUARE {}
Tree { y 1 }
}
rule Tree 0.2 {
CIRCLE { y -0.5 }
Tree { y -0.5 r 30 s 0.75 }
Tree { y -0.5 r -30 s 0.75 }
}
rule Tree 0.01 {
CIRCLE { y -0.5 }
}
見た目は複雑なイメージですが、コードの内容は単純です。 startshapeが呼び出すルールのTreeは3種類あり、それぞれにウエイトが設定されています。 最初のTreeは正方形で木の幹を描き、Treeをy軸方向に1個分移動して再帰呼び出しします。 幹はそれなりの長さが必要なので、ウエイトを3種類のうちで最も大きい0.6としています。 次のTreeは枝分かれです。分岐点の円を描き、左右に30度かたむけ、スケールを0.75に縮小して2つのTreeを再帰呼び出しします。 ときどき枝分かれすればいいので、ウエイトは0.2です。 最後のTreeは終了ルールで、再帰呼び出しせずに処理を終了します。 まれに終了すればいいのでウエイトは0.01にしています。 枝分かれのTreeでスケールを縮小していますから(描画できない大きさになれば終了するので)終了ルールがなくてもいいのですが、途中でぶっつり切れた枝ということで採用しました。 円を描いて描画を終了します。
ちなみに、終了ルールなしの場合はこんな感じになります。
startshape Tree
rule Tree 0.6 {
SQUARE {}
Tree { y 1}
}
rule Tree 0.2 {
CIRCLE {y -0.5}
Tree { y -0.5 r 30 s 0.75 }
Tree { y -0.5 r -30 s 0.75 }
}
再帰呼び出しとウエイトによるルールの分岐制御はContext Freeの特徴のひとつです。 実行のたびに違ったイメージが現れるのが楽しいですね。
できるようになった(はずの)こと- 再帰呼び出しを使ってシェイプを描画できる
- 再帰呼び出し終了条件を設定できる