以前,JavaScriptでヒルベルト曲線を描くプログラムを紹介した.今回は,Pythonのタートルグラフィクスライブラリを使って同様のヒルベルト曲線を描くプログラムである.
ヒルベルト曲線に限らずフラクタルは再帰の考え方で描くことができるが,まさに下記の関数がそれを表している.こんなに簡単に表現することができるのは素晴らしい.NumPyを利用して行列演算をたんなる掛け算として表すことができる点も,単純化に寄与している要因である.
def hilbert(n, m):
if n > 1:
for m_ in tm: hilbert(n-1, m * m_)
else:
for q in [ m * p_ for p_ in p ]: draw_line_to(q)
なお,一時的に用意している「m_」や「p_」といった変数は,とくに名前を付ける必要はないのでアンダースコア1文字で次のように表現することも許されているらしい.しかし,ここまでやるのは少しやり過ぎな気もする.
def hilbert(n, m):
if n > 1:
for _ in tm: hilbert(n-1, m * _)
else:
for q in [ m * _ for _ in p ]: draw_line_to(q)
タートルグラフィクスなので,これだけのプログラムでアニメーション動作する.動画を用意した.ずっと眺めていても飽きないゾ?
プログラムの全体は以下のとおりである.
#!/usr/bin/env python
from turtle import *
import numpy as np
SIZE = 300
MARGIN = 50
penup_flag = True
settings = [ { 'color': x[0], 'width': x[1] } for x in [
['forestgreen', 5], ['navy', 4], ['purple', 3], ['brown', 2],
['red', 2], ['orange', 1], ['yellowgreeen', 1] ] ]
tm = [ np.matrix(x) for x in [
[ [0.0, -0.5, -0.5], [-0.5, 0.0, 0.5], [0.0, 0.0, 1.0] ],
[ [0.5, 0.0, -0.5], [ 0.0, 0.5, -0.5], [0.0, 0.0, 1.0] ],
[ [0.5, 0.0, 0.5], [ 0.0, 0.5, -0.5], [0.0, 0.0, 1.0] ],
[ [0.0, 0.5, 0.5], [ 0.5, 0.0, 0.5], [0.0, 0.0, 1.0] ] ] ]
e = np.eye(3)
p = [ np.matrix(x).T for x in [
[-0.5, 0.5, 1.0], [-0.5, -0.5, 1.0],
[ 0.5, -0.5, 1.0], [ 0.5, 0.5, 1.0] ] ]
def draw_line_to(x):
goto(x[0,0]*SIZE, x[1,0]*SIZE)
global penup_flag
if penup_flag:
pendown()
penup_flag = False
def reset():
penup()
global penup_flag
penup_flag = True
def hilbert(n, m):
if n > 1:
for m_ in tm: hilbert(n-1, m * m_)
else:
for q in [ m * p_ for p_ in p ]: draw_line_to(q)
setup(width = 2*SIZE+MARGIN, height = 2*SIZE+MARGIN)
for i in range(len(settings)):
reset()
color(settings[i]['color'], 'white')
width(settings[i]['width'])
hilbert(i+1, e)
onkey(exit, 'q')
listen()
mainloop()
0 件のコメント:
コメントを投稿