Turtleグラフィックス⑥ フラクタル図形
フラクタル図形
Turtleグラフィックスを利用して フラクタル図形 を描いてみましょう. フラクタル図形 とは,図形の一部が図形の全体と 自己相似 な関係を持つ図形のことです. 特定の処理を再帰的に繰り返して実行することで描くことができます. フラクタル図形は自然界でも観測が可能で,「シダの葉」や「雲の形」はフラクタル図形とされています. ここでは,フラクタルの性質を持つ「コッホ曲線」と「2分木」を描くことに挑戦しましょう.
準備
Muエディタを起動したら,Python3 モードを選択しましょう. ツールバーにある「保存」をクリックして,「chapter7.py」という名前でスクリプトを保存します. また,Turtleグラフィックスのライブラリ(モジュール)をインポートしておきましょう.
# Turtleグラフィックスのライブラリをインポート
from turtle import *
コッホ曲線
コッホ曲線は次の図に示す操作を再帰的に適用することで描くことができます. 直線を三分割し,中央の線分を底辺とした正三角形を描きます. このとき,図形全体を構成する4つの線分は同じ長さとなります. この処理を,各線分に対して再起的に適用することで, 2次,3次など高次のコッホ曲線を描くことができます.
再帰を利用しない実装
関数koch()
を定義して,再帰を利用しない方法で1次のコッホ曲線を描いてみましょう.
# 1次のコッホ曲線
def koch(length):
next_length = length / 3
forward(next_length)
left(60)
forward(next_length)
right(120)
forward(next_length)
left(60)
forward(next_length)
speed(0)
penup()
goto(-200, 0)
pendown()
length = 400 # 直線の長さ
koch(length)
上記の1次のコッホ曲線の最初の辺だけ2次に変更してみましょう.
最初のforward(next_length)
を,自己相似となるように,次のように置き換えます.
このとき,2次のコッホ曲線の1辺の長さはlength
の1/9になります.
# 1次のコッホ曲線(最初の辺だけ2次に)
def koch(length):
next_length = length / 3
#----------
# 最初の辺だけ2次に変更
next_next_length = length / 3 / 3
forward(next_next_length)
left(60)
forward(next_next_length)
right(120)
forward(next_next_length)
left(60)
forward(next_next_length)
#---------
left(60)
forward(next_length)
right(120)
forward(next_length)
left(60)
forward(next_length)
例題1
再帰を利用しないで2次のコッホ曲線を完成させてください.
再帰を利用した実装
関数koch()
を,再帰を利用してコッホ曲線を描くように修正しましょう.
forward(next_length)
が,koch(n-1, next_length)
に置き換わっています.
再帰的にkoch()
を実行するときは,次元n
を1だけ小さくし,n
が0になったときに再帰処理を停止しています.
# n次のコッホ曲線
def koch(n, length):
if n == 0:
forward(length)
return # 再帰の終了
# n-1次の直線の長さ
next_length = length / 3
koch(n-1, next_length)
left(60)
koch(n-1, next_length)
right(120)
koch(n-1, next_length)
left(60)
koch(n-1, next_length)
speed(0)
penup()
goto(-200, 0)
pendown()
n = 0 # 次数
length = 400 # 直線の長さ
koch(n, length)
n = 1 # 次数
length = 400 # 直線の長さ
koch(n, length)
n = 2 # 次数
length = 400 # 直線の長さ
koch(n, length)
n = 3 # 次数
length = 400 # 直線の長さ
koch(n, length)
2分木
2分木は次の図に示す操作を再帰的に適用することで描くことができます. 1次では直線を描き,2次では左の枝と右の枝に分岐します. 左の枝は,左に30°回転し,その長さを0.8倍します. 右の枝は,右に30°回転し,その長さを0.5倍します. この処理を,再起的に適用することで,3次,4次など高次の2分木を描くことができます.
再帰を利用しない実装
関数tree()
を定義して,再帰を利用しない方法で2次の2分木を描いてみましょう.
# 2次の2分木
def tree(length, angle):
forward(length)
# 左の枝
left(angle)
next_left_length = 0.8 * length # 枝の長さを0.8倍
forward(next_left_length)
backward(next_left_length)
# 右の枝
right(angle * 2)
next_right_length = 0.5 * length # 枝の長さを0.5倍
forward(next_right_length)
backward(next_right_length)
# 始点に戻る
left(angle)
backward(length)
speed(0)
penup()
goto(100, -200)
setheading(90)
pendown()
length = 150 # 枝の長さ
angle = 30 # 分岐の角度
tree(length, angle)
上記の2次の2分木の左の枝だけ3次に変更してみましょう.
最初のforward(next_left_length)
とwabckward(next_left_length)
を,自己相似となるように,次のように置き換えます.
このとき,3次の2分木の左の枝の長さはlength * 0.8 * 0.8
,右の枝の長さはlength * 0.8 * 0.5
になります.
# 2次の2分木(左の枝だけ3次に)
def tree(length, angle):
forward(length)
# 左の枝
left(angle)
next_left_length = 0.8 * length # 枝の長さを0.8倍
#----------
# 左の枝だけ2次に変更
forward(next_left_length)
# 左の枝
left(angle)
next_next_left_length = 0.8 * next_left_length # 枝の長さを0.8倍
forward(next_next_left_length)
backward(next_next_left_length)
# 右の枝
right(angle * 2)
next_next_right_length = 0.5 * next_left_length # 枝の長さを0.5倍
forward(next_next_right_length)
backward(next_next_right_length)
# 始点に戻る
left(angle)
backward(next_left_length)
#----------
# 右の枝
right(angle * 2)
next_right_length = 0.5 * length # 枝の長さを0.5倍
forward(next_right_length)
backward(next_right_length)
# 始点に戻る
left(angle)
backward(length)
例題2
再帰を利用しないで3次の2分木を完成させてください.
再帰を利用した実装
関数tree()を,再帰を利用して2分木を描くように修正しましょう. コッホ曲線と同じように,再帰的にtree()を実行するときは,次元nを1だけ小さくし,nが0になったときに再帰処理を停止しています.
# n次の2分木
def tree(n, length, angle):
if n == 0:
return # 再帰の終了
forward(length)
# 左の枝
left(angle)
next_left_length = 0.8 * length # 枝の長さを0.8倍
tree(n-1, next_left_length, angle)
# 右の枝
right(angle * 2)
next_right_length = 0.5 * length # 枝の長さを0.5倍
tree(n-1, next_right_length, angle)
# 始点に戻る
left(angle)
backward(length)
speed(0)
penup()
goto(100, -200)
setheading(90)
pendown()
n = 2 # 次数
length = 150 # 枝の長さ
angle = 30 # 分岐の角度
tree(n, length, angle)
n = 4
length = 150
angle = 30
tree(n, length, angle)
n = 6
length = 150
angle = 30
tree(n, length, angle)
n = 8
length = 150
angle = 30
tree(n, length, angle)
課題
次の課題に取組んでください.
- 次の図を参考に中央の線分を正方形に置き換えたコッホ曲線を描いてください
- 1次,2次,3次のコッホ曲線を描いてください(提出の際は3次のコッホ曲線とすること)
課題を完成させたらスクリプトを保存し,「chapter7.py」を提出してください.