東北大学片平キャンパスの構内にはプラタナスの木が沢山植えられているが、実を付ける木は一本しか知らない。昨年、その実を被写体にして写真を撮ったが枯葉の時期のものだった。今年は少し早めに写真を撮った。葉がまだ緑の時期のプラタナスの実である:


東北大学片平キャンパスの構内にはプラタナスの木が沢山植えられているが、実を付ける木は一本しか知らない。昨年、その実を被写体にして写真を撮ったが枯葉の時期のものだった。今年は少し早めに写真を撮った。葉がまだ緑の時期のプラタナスの実である:
「栽培植物と農耕に起源」(中尾佐助著)によれば人類は農業で4次に渡る「農業革命」を成し遂げている。
現在の日本は第二次農業革命を経過したレベルにあるという。
「栽培植物と農耕に起源」(中尾佐助著)では栽培植物の元になった野生種の所在から世界の農業の起源を四つの地域に分類している。
これらのなかで人類の歴史上で最初の農業と言えるものは最も原始的であるが「根菜農耕文化」である。
稲の起源に触れて「栽培植物と農耕に起源」(中尾佐助著)の中で述べられている語句である。
アフリカやインドのサバンナ農耕文化は雑穀の文化である。このサバンナ農耕文化でも夏のモンスーン雨期には禾本科の草の穀物を採取して食料としていた。この周辺の雨の多い地帯で食料とされた湿生の雑穀の一つがイネであった。それは西アフリカとインド東部を起源とする。
Pythonのタートル・グラフィックスはTkinterを基礎に作られているのでTkinterのcanvasウィジェット上にタートル・グラフィックスで描画を行うことは容易である。しかもTkinterのメニューなどの他のウィジェットも画面構成に使える。ここでは本物らしく木を描くタートル・グラフィックスをcanvas上で実行し、入力パラメタをentryウィジェットを使って入力するようにする。サンプル画像を以下に示す:
左側がcanvasで、右側がentryを含むメニューである。「Turbo Graphics」(安齋利洋・伊吹龍著;1987年)では二種類(単子葉植物、双子葉植物)の木の描画アルゴリズムが載っているがここではメニューで種類を選べるようにしてある。
Pythonのプログラムはここにある。
中華どんぶりに描かれているような「一筆書き」である。このような描画はPythonのタートル・グラフィックスが得意とするものである。「Turbo Graphics」(安齋利洋・伊吹龍著;1987年)に載っているPascal風のプログラムをなぞって作ったのが以下のものだ(元のプログラムにあったkameの大域変数は関数の引数とするようにした)。
#coding: utf-8
import myturtle
depth = 7 #再帰の深さ
atom = 3 #最小の長さ
def deko(kame, level):
if(level == 0):
return
else:
kame.reverse()
kame.rt(90)
deko(kame, level-1)
kame.reverse()
kame.fd(atom)
kame.rt(90)
deko(kame, level-1)
kame.fd(atom)
deko(kame, level-1)
kame.rt(90)
kame.fd(atom)
kame.reverse()
deko(kame,level-1)
kame.rt(90)
kame.reverse()
if __name__ == '__main__':
kame = myturtle.MyTurtle()
kame.ht()
kame.setposition(-300,-300)
kame.clear()
deko(kame, depth)
このプログラムでは二つの定数(depth, atom)が定義されているが、atomは描画が画面内に納まるようにするためのものである。定数depthは再帰の深さを示すものでこの曲線にとっては本質的なものである。
定数depthを大きくしたときの描画は実に奇妙である。以下depth=8の例を示す:
一本の線分(両端がある)にも拘わらず平面を埋め尽くすような描画ができる。再帰の深さ(depth)を無限大にする極限でこの線分は平面を文字通り埋め尽くして平面を作ることが知られている。
有名なコッホ(Koch)曲線を描く。「Turbo Graphics」(安齋利洋・伊吹龍著;1987年)に載っているPascal風のプログラムをなぞって作ったのが以下のものだ:
#coding: utf-8
import myturtle
depth = 5 #再帰の深さ
def koch(length, level):
global kame
if(level > 0):
len1 = length /3
koch(len1, level-1)
kame.lt(60)
koch(len1, level-1)
kame.rt(120)
koch(len1, level-1)
kame.lt(60)
koch(len1, level-1)
else:
kame.fd(length)
if __name__ == '__main__':
kame = myturtle.MyTurtle()
kame.ht()
kame.setposition(-320,-0)
kame.clear()
koch(640, depth)
【描画】
複雑であるが折れ線による「一筆描き」である。このような「一筆描き」ではあるセグメントの折れ線ではこれまで描かれた折れ線の先端を起点として一つの折れ線を描き、その折れ線の先端は次の折れ線の起点となるような処理が必要となる。上のプログラムではこれをkameを大域変数(global)とすることで行っている。こうすることでkameが折れ線を描く毎にkameの属性(位置)が更新される。
このような事情を考慮して直接Pythonで書くと以下のようになる:
#coding: utf-8
import myturtle
depth = 5 #再帰の深さ
def koch(kame, length, level):
if(level > 0):
len1 = length /3
koch(kame, len1, level-1)
kame.lt(60)
koch(kame, len1, level-1)
kame.rt(120)
koch(kame, len1, level-1)
kame.lt(60)
koch(kame, len1, level-1)
else:
kame.fd(length)
if __name__ == '__main__':
kame = myturtle.MyTurtle()
kame.ht()
kame.setposition(-320,-0)
kame.clear()
koch(kame, 640, depth)
このプログラムではkameは関数kochの引数の一つとして関数kochに渡されるようになっている。このプログラムはPascal風の処理系では期待通りの結果は得られないが、Pythonでは上の描画と同じものが得られる。Pythonでは関数に渡されたオブジェクトkameは関数内の変更を受けて実引数のkameの属性も変更されるからだ。
Pythonではkameを大域変数とするプログラムも、kameを関数の引数として渡すプログラムも作れる。後者は少しトリッキーな気もするが。
「Turbo Graphics」(安齋利洋・伊吹龍著;1987年)には本物らしく木を描画するプログラムが紹介されている。オリジナルのアルゴリズムは本田久夫氏(「樹木の分枝」別冊『数理科学』形・フラクタル、p78)との注がある。
プログラムは描画のためのパラメターをファイルから読み込むなど凝ったものになっているがここでは描画のエッセンスだけを抜き出しPythonで書いてみた:
#coding: utf-8
import myturtle
#パラメター
xP=0
yP=-300
angleMiki=15
ratioMiki = 0.80
angleEda=45
ratioEda=0.70
length=150
ratioFutosa=0.7200
generation=10
class Seed:
"""木の表現のためのパラメター類"""
def ki(tane):
def edawakare(mikiT, length, thickness, depth):
if(depth ==0 or length < 2 or thickness < 0.1):
return
miki=mikiT.clone()
miki.reverse()
miki.fd(length)
eda=miki.clone()
miki.lt(tane.angleMiki)
edawakare(miki, length*tane.ratioMiki, thickness, depth-1)
eda.rt(tane.angleEda)
edawakare(eda, length*tane.ratioEda, thickness*tane.ratioFutosa, \
depth-1)
miki=myturtle.MyTurtle()
miki.ht()
miki.lt(90)
miki.setposition(tane.xP, tane.yP)
miki.clear()
edawakare(miki, tane.length, 1, tane.generation)
if __name__ == '__main__':
tane=Seed()
tane.xP=xP
tane.yP=yP
tane.angleMiki=angleMiki
tane.ratioMiki=ratioMiki
tane.angleEda=angleEda
tane.ratioEda=ratioEda
tane.length=length
tane.ratioFutosa=ratioFutosa
tane.generation=generation
ki( tane)
ここでは関数内ではクローンturtleを使っている。
【実行結果の描画】