![見出し画像](https://assets.st-note.com/production/uploads/images/73606806/rectangle_large_type_2_f21bebe31f9d62b7a6c34be57cd669be.png?width=1200)
ボルボックス的な何か
猫もそうであるが、生物をプログラムにより描画したいという欲求を私は持っている。猫のような高等生物をアルゴリズミックに描くことはおそらく難しいのではないだろうか。一方、微生物については猫よりも単純な形をしているものも多い。アルゴリズムによる生物の描画も、個体発生は系統発生を繰り返すという言説が当てはまるのかもしれない。
そこで、今回は引き続きボルボックスをテーマとしてプログラムを作ってみよう。ボルボックスの写真はもとより、それを模式的に描画するイラストを眺めて構想を練る。
基本的には円の中に細かな円と、ある程度大きな円を描画するという規則がみてとれる。
そこで、円領域に細かな円を描画するところからプログラムを作ってみる:
size(500,500)
noFill()
R=random
background(-1)
for i in [0]*1000:
x=R(500);y=R(500);r=R(10)
if dist(250,250,x,y)+r<250:
circle(x,y,r)
![](https://assets.st-note.com/img/1646532038547-zSzn7DPMFt.png?width=1200)
なかなか良い感じである。
描画される小さな円が、画面全体を覆う見えない大きな円の中に収まるか否かの判定は、dist(250,250,x,y)+r が 250 より小さいか否かで判定している。
この式の意味であるが、画面のサイズが 500x500 なので、見えない大きな円の中心は (250,250) である。ランダムに決めた小さな円の中心 (x,y) と点 (250,250) との距離に、これまたランダムに決めた小さな円の半径 r を加えても、250 よりも小さいのであれば、それは中心 (250,250)、半径 250 の円に収まることに他ならない。
ボルボックスの構造は内部にさらに小さなボルボックスが存在するようにも見える。このような入れ子になった構造を描画する場合、再起処理を用いるのが便利だ。
そのため、描画処理を関数として切り出す。この際に、描画領域の円の中心 (p,q) と半径 t をとり、内部にどれだけの小さな円を発生させるかを支持する引数 n と、際限なく再帰呼び出しをしないようにするための打ち切り情報用の引数 l もとるようにする。
ついでに、先程は見えない円領域として指定していた領域も描画するようにし、色もボルボックス的になるよう緑色で着色する。
そんなことを考えながら作成したのが以下のコードである。
R=random
def D(p,q,t,n,l):
circle(p,q,t*2)
circle(p,q,t*2+2)
for i in [0]*n:
x=R(500);y=R(500);r=R(5)
if dist(p,q,x,y)+r<t:
circle(x,y,r)
if l>0 and R(1)<.05:D(x,y,(t-dist(p,q,x,y))/(l*3),n/9,l-1)
size(500,500)
noFill()
background(-9)
stroke(50,90,20,80)
D(250,250,250,11000,3)
![](https://assets.st-note.com/img/1646532644744-ykEeKKVUGH.png?width=1200)
これまでの作品の中では最もボルボックス的な絵となったような気がする。
この作品を #つぶやきProcessing 化するのは無理か…と思いつつ、一応試してみた。background 指定を外したり、if 文の除去を行ったりしたら、なんとか 1 tweet に収めることができた。
雰囲気もあまり変わってないのが幸いである。諦めずに試してみるものだ。
R=random
— Koji Saito (@KojiSaito) March 6, 2022
C=circle
def D(p,q,t,n,l):
C(p,q,t*2);C(p,q,t*2+2)
for i in [0]*n:
x=R(500);y=R(500);r=R(5)
if dist(p,q,x,y)+r<t:C(x,y,r);l>0 and R(1)<.05 and D(x,y,(t-dist(p,q,x,y))/(l*3),n/9,l-1)
size(500,500)
noFill()
stroke(50,90,20,80)
D(250,250,220,9999,3)#つぶやきProcessing pic.twitter.com/h0H43UBagD
ちなみに if 文の除去方法については、以下のコードを、
if l>0 and R(1)<.05:D(x,y,(t-dist(p,q,x,y))/(l*3),n/9,l-1)
このように辺形している:
l>0 and R(1)<.05 and D(x,y,(t-dist(p,q,x,y))/(l*3),n/9,l-1)
論理積演算子(and 等)は条件が一つでも偽であれば、論理式全体の値は偽となる。そのため、途中で偽の値が出現した時点でそれ以降の計算を行わないという言語仕様を持つプログラム言語もある。代表的なプログラミング言語としては C が良くしられているが、Python もそうである。
この仕様を利用して、このように if 文を除去できる。上記のコードでは l>0 and R(1)<.05 が真である時に限り関数 D の呼び出しが行われる。これはつまり、先に if 文を用いて書いた処理と同値であることに他ならない。
Python モードで #つぶやきProcessing を行う場合は、Python 特有のインデントによるブロック指定を、どのようにかわしていくかが重要となる。このような独特の技法を用いて文字数削減するのも、Python モードにおける #つぶやきProcessing の楽しみのひとつでもある。