見出し画像

PythonでL-Systemsを作る(1) タートルグラフィクス

 L-systems(Lindenmayer systems)は、植物の成長プロセスを初めとした様々な自然物の構造を記述・表現できるアルゴリズムである。1968年、理論生物学者であり植物学者のアリステッド・リンデンマイヤーによって植物(酵母、菌や藻類)の成長過程や構造・相互関係等を表現するための方法として開発され、その後高度な植物へと発展した。見出し画像が植物の描画の例だ。

 自然物の他にも、自己相似図形やフラクタル図形を簡単に記述できる。
 L-systemsでは、初期条件と規則性を示す文字列をタートルの制御命令に変換して、タートルグラフィックスで図形を描画する。このシリーズでは,リンデンマイヤーの「The Algorithmic Beauty of Plants」に基づいて,PythonでL-Systemsを作っていく。
 タートルグラフィクスなので,高校の情報の授業でも使うことができる。今進められている学校でのプログラミング教育では,小学校でタートルグラフィクスを用いた多角形を選ぶ例がある(文科省:小学校プログラミング教育の手引き)。そのために Scratch やドリトルを小・中学校で使った経験があるなら,高校でもタートルグラフィクスは導入として使えるだろう。
筆者はCindyScriptで作ったL-Systemsを使って情報の実習を行ったことがある。それについても後述しよう。

タートルグラフィクスとは

 コンピュータの画面上に「亀」がいる。(亀は英語でturtle: タートル)この亀は、命令にしたがって、画面上を前または後ろにまっすぐ進むことと、向きを変えることができる。この亀に適当な指示を与えて動かすと、亀が動いたあとが図形として描かれる。こうして図形を描くのが「タートルグラフィクス」である。タートルグラフィクスを根幹に置いたプログラミング言語がLOGO。LOGOは1967年にシーモア・パパートによって開発されたが、1980年代にパソコンが普及し、学校でも使われるようになると、教育用プログラミング言語として脚光を浴びた。日本でも、「みかんLOGO」などのプログラミング言語が開発された。現在最もよく使われているのはドリトル や Scratch だろう。タートルグラフィクスだけではなく、音楽などもでき,一般のプログラミング言語のような記述もできる。LOGOでは、小学生にもわかるタートルグラフィクスを扱うので、「座標」や「座標系」という言葉は登場しない。真っ白な紙の上で、「まえへ10」「みぎへ30°」といった命令を実行していく。しかし、高校生になれば座標の概念もわかるので,次のような説明も可能となる。

(1) 亀がどこにいても動かない座標系(原点とx軸、y軸の直交座標)がある。
(2) 亀は動いたあと、常に自分が原点にいて、x軸の正の方向を向いていると思っている。

(1) を「絶対的な座標系」(2)を「相対的な座標系」という。赤の矢線の先に亀がいる。亀にとっては自分のいる位置が原点で,向いている方がx軸(進行方向)になる。

画像1

Pythonのタートルグラフィクス

 Pythonでは,タートルグラフィクスのライブラリ(モジュール)turtle が標準で使える。Tkinterがベースになっている。
 ただし,Jupyter Notebookで使うには若干不具合がある。描画を終えてウィンドウを閉じようとしても閉じることができなかったり,閉じた後でエラーになることだ。閉じることができない場合はPythonを強制終了する。エラーになる場合は,かまわず再実行すればよい。IDLEでは正常に動作する。
 また,Google Colaboratory では turtle のインポートはできない。かわりに,ColabTuetle.Turtle を 次のようにしてインポートする。

!pip3 install ColabTurtle
from ColabTurtle.Turtle import *

この他,描画終了を done() または mainloop() で宣言するが,Google Colaboratory ではこれは不要だ。
Google Colaboratory でのタートルグラフィクスについては,note 上に次の記事がある。シリーズになっていて参考になる。

この中にある星形五角形を,Pythonのturtle モジュールを使って描いてみよう。
亀になったつもりで動き方を考える。

(1) はじめに36度左を向く。(そうするとまっすぐに立った星形が描ける)
(2) 一歩進む。Pythonでは単位がピクセル。たとえば100ピクセルを1歩とする。
(3) 144度左を向く。ここが大切。何度左を向くか,亀になったつもりでないと
  ただしくとれない。
(4) (2)(3)を5回繰り返せば星形が描ける。

import turtle as kame
kame.shape("turtle")
kame.color('green')
kame.setheading(36)
for i in range(5):
   kame.forward(100)
   kame.left(144)
kame.done()

kame.shape("turtle") はタートルの形を亀にする。初期状態では矢線の矢じり。
kame.color('green') は亀とペンの色。みどり亀にした。

1行目を from turtle import* とすれば,短縮名 kame も使わずに済むが,このあたりはどちらがいいかは何とも言えない。ドリトルを使ってきた人は かめ! で命令するのに慣れているだろうから,forward より kame.forward の方がイメージしやすいかもしれない。

画像2

円を描く

 星形ではない正多角形を,辺の数を多くして描くと円に近くなる。ただし,Pythonの turtle グラフィクスではなかなか滑らかな円にならない。

画像3

円と内接多角形,外接多角形を描く

 高校であれば,円と内接多角形,外接多角形を描くことができる。回転角は簡単に三角関数を使う必要がある。たとえば,次のプログラムではうまく描けない。

for i in range(180):
   kame.forward(4)
   kame.left(2)
kame.setheading(30)
for i in range(6):
   kame.forward(120)
   kame.left(60)

画像4

円の半径と辺の長さの関係をきちんと計算しないといけないわけだ。
正六角形の場合は,半径と辺の長さは同じだ。したがって,次のコードでは半径120の円に内接する正六角形を描いたことになる。

for i in range(6):
   kame.forward(120)
   kame.left(60)

では,同じ半径で180角形(ほとんど円)はどう描く? 角度は2°でよいが,亀が進む距離は?

それを考えるための図を亀に描かせてみた。

画像5

正三角形は六角形の一部。円の中心から辺に垂線を下す。できた直角三角形の角は30°と60°だ。すると,短辺:正六角形の1辺の半分は sin で計算できる。半径を r とすると r sin30° になる。亀の進む距離はその2倍である。次のプログラムが,この図を描かせたものだ。

import numpy as np
import turtle as kame
kame.shape("turtle")
# 正三角形と垂線を下した図を描く 1120
kame.forward(120)
kame.left(120)
kame.forward(120)
kame.left(120)
kame.forward(120)
kame.left(150)
kame.forward(120*np.cos(np.pi/6))
kame.backward(20)
kame.right(90)
kame.forward(20)
kame.left(90)
kame.forward(20)
# 円を描くスタート地点に移動
kame.penup()
kame.goto(0,-120)
kame.setheading(0)
kame.pendown()
# 円を描く 半径120
r = 240*np.sin(np.pi/180)
for i in range(180):
   kame.forward(r)
   kame.left(2)
   
kame.done()

外接多角形も同様に考えればよい。今度は tan を使う。

画像6

 三角関数(1年生の三角比でよい)を学んだ高校生にはちょうどよい演習問題になる。実際に授業でこの課題を与えたが,できた生徒は少なかった。三角関数を用いた計算ができないのである。三角関数・三角比をちゃんと理解できていないともいえるだろう。公式を暗記していても,実際の場面で使えない。プログラミングとはそういうものである。必要なのはアルゴリズムを考える思考力と,それをささえる知識である。

L-Systems でのタートルグラフィクス

 L-Systems で用いるタートルグラフィクスは,LOGOのものとは若干異なる。前進と回転は同じだが,後退はない。また,LOGOにはないコマンドもある。コマンドの与え方も異なる。L-Systems で使うコマンドは次のもので,これを文字列として命令文とする。

 F,A,B 前進して軌跡を描く。
 f   前進するが軌跡は描かない。
 +   左(時計回りの方向)に指定された角度だけ回転する。 
 -   右に回転する。
 [   現在の状態を記憶する。
 ]   記憶した状態に戻す。
 S など,A,B,F 以外の文字では何もしない。

星形五角形でいうと次のようになる。はじめに36度の方に向いているものとする。次の文字列が命令文だ。

    F+F+F+F+F+

したがって,一歩の長さと回転角を途中で変えることはしない。

====================================

次回は,L-Systems の中核になる「置き換えシステム」について解説しよう。ここでフラクタルの一つで有名なコッホ曲線が登場する。

(2) 置き換えシステム