プログラムでシダを描画する
プログラマーであれば誰もが描画したくなるシダ。
自分もご多分にもれず描画したく成ってしまったので計算式を求めてググってみた所、こちらの動画を発見。
こちらの動画には十進BASIC向けの以下のコードが記載されていました。
【十進BASIC用のコード】
SET TEXT BACKGROUND "OPAQUE" LET t$="シダ" LET N=20 LET xm=0 LET ym=0.5 LET h=0.6 !---------------------------- SET WINDOW xm-h, xm+h, ym-h, ym+h DRAW axes PLOT TEXT,AT xm+h*0.1,ym+h*0.85:t$ PLOT TEXT,AT xm+h*0.5,ym+h*0.85, USING "N =%%":N PLOT TEXT,AT xm-h*0.75, ym+h*0.85:"しばらくおまちください" SET POINT STYLE 1 SET POINT COLOR 10 !51 CALL f(N, 0,0) beep PLOT TEXT,AT xm-h*0.75, ym+h*0.85:"描画終了" !------------------------------------------------------------ DEF W1x(x,y)=0.836*x+0.044*y DEF W1y(x,y)=-0.044*x+0.836*y+0.169 ! p1=0.4 DEF W2x(x,y)=-0.141*x+0.302*y DEF W2y(x,y)=0.302*x+0.141*y+0.127 ! p2=0.2 DEF W3x(x,y)=0.141*x-0.302*y DEF W3y(x,y)=0.302*x+0.141*y+0.169 ! p3=0.2 DEF W4x(x,y)=0 DEF W4y(x,y)=0.175337*y !p4=0.2 !------------------------------------------------------------ SUB f(k, x,y) IF 0<k THEN CALL f(k-1,W1x(x,y),W1y(x,y)) IF RND<0.3 THEN CALL f(k-1,W2x(x,y),W2y(x,y)) IF RND<0.3 THEN CALL f(k-1,W3x(x,y),W3y(x,y)) IF RND<0.3 THEN CALL f(k-1,W4x(x,y),W4y(x,y)) ELSE PLOT POINTS:x,y END IF END SUB END
行番号の付いてない様な高度なBASICはさっぱり読めないのですが勘で Processing に移植してみました(十進BASICでは ! はコメントに使うっぽいというのに気がつくまでちょっとだけ苦戦させられましたw)。
【 Processing 用のコード】
int N=20; float xm=0; float ym=0.5; float h=0.6; float W1x(float x, float y) { return 0.836*x+0.044*y; } float W1y(float x, float y) { return -0.044*x+0.836*y+0.169; } float W2x(float x, float y) { return -0.141*x+0.302*y; } float W2y(float x, float y) { return 0.302*x+0.141*y+0.127; } float W3x(float x, float y) { return 0.141*x-0.302*y; } float W3y(float x, float y) { return 0.302*x+0.141*y+0.169; } float W4x(float x, float y) { return 0; } float W4y(float x, float y) { return 0.175337*y; } void f(int k, float x, float y) { if (0<k) { f(k-1, W1x(x,y), W1y(x,y)); if (random(1.0) < 0.3) f(k-1, W2x(x,y), W2y(x,y)); if (random(1.0) < 0.3) f(k-1, W3x(x,y), W3y(x,y)); if (random(1.0) < 0.3) f(k-1, W4x(x,y), W4y(x,y)); } else { float s = 490; point(x*s+width*.5, height-y*s); } } void setup() { background(255); size(500, 500); stroke(0, 128, 0); f(N, 0, 0); }