Tiny Code ExamplesJ小さなプログラム例この節では、CindyScript を使った小さなプログラムの例をあげます。それぞれの例は、CindyScript でいろいろなものの取り扱いかたを示します。 重心3つの点の重心 D を設定します。状況により色が変わるようにします。この例では、点Dのx座標の正負により色が変わります。 //in draw D.xy=(A+B+C)/3; D.color=if(D.x>0, (1,1,0), (0,0,1) ) // in draw とあるのは、Drawスロットに書く、という意味です。 このコードは順番に実行されます。点Dの位置を計算して D.xy に代入することでDの位置が決まります。点Dの色はDの位置によって if 文で設定されます。選択と集積x軸の上下で点を分類してネットワーク状に線で結びます。適当に点をいくつかとっておいて次のスクリプトをdrawスロットに書いて実行します。 //in draw pts=allpoints(); above=select(pts,p,p.y>0); below=pts--above; segs=pairs(above); drawall(segs,color->(0.6,0,0)); segs=pairs(below); drawall(segs,color->(0,0.6,0)) x軸より上の点を select 演算子により選びだします。それを全体から引くとx軸より下の点が得られます。 pairs 演算子で点を2つずつ結びます。凸型外殻の描画すべての点を内部に含む凸型の外殻を描きます。数の不安定性に対処する ~> 演算子の働きを見てください。//in draw pts=allpoints(); leftof(A,B):=select(pts,p,area(A,B,p)~>0); rightof(A,B):=select(pts,p,area(A,B,p)~<0); isedge(A,B):=(leftof(A,B)==[]%rightof(A,B)==[]); segments=pairs(pts); hull=select(segments,seg,isedge(seg_1,seg_2)); drawall(hull); 凸型外殻の計算は非常にうまい幾何学的原則によってなされます。凸型外殻の中にすべての点が入ります。 leftof と rightof というユーザー定義関数は線分ABのどちら側にあるかで点を分類します。さらにこれを用いて isedge を定義し2つの点のペアが凸型外殻の端となるかどうかを調べます。ここで、あいまいな比較 ~<0 の使い方に着目してください。最後に、すべての端の線を描画します。アナログ時計時針、分針、秒針をもったアナログ時計を作ります。まず、原点を始点とする3つの矢線を描いておきます。その終点をB,C,Dとします。それから次のスクリプトを Timer Tick スロットに書いて実行します。 //in timerstep t=time(); p(x):=(sin(2*pi*x),cos(2*pi*x)); B.xy=p(t_3/60)*4; C.xy=p(t_2/60)*5; D.xy=p((t_1*60+t_2)/(12*60))*3.5; apply(1..12,i,draw(p(i/12)*5)); apply(1..60,i,draw(p(i/60)*5,size->1)); drawtext((3,5),t); 点はスクリプトで描きます。時計盤の円は「円を描く」モードで描いておきます。この時計は、 time 関数がコンピュータのシステム時間にアクセスするのを利用しています。tがリストであることを利用して秒針は1秒ごとに動くようになっています。最短距離にある点点Aに最も近い点を緑の円で囲んで示します。 //in draw pts=allpoints(); s=sort(pts,|#-A|); p=s_2; draw(p,size->20); 上のコードではA自身が最短になるために、距離で並べ替えた後、2番目に近いものをとっています。もうひとつの方法は、あらかじめ点Aを除外しておくものです。次のコードをご覧ください。 //in draw pts=allpoints()--[A]; s=sort(pts,|#-A|); p=s_1; draw(p,size->20); 簡単な模様点を動かして簡単な模様を描きます。線の色は点の色がそのまま使われます。まず、点をいくつかとり、色を変えておきます。(下図では3つ)//in draw 以下のスクリプトを Drawスロットに、// in init 以下を Initializationスロットに書いて実行します。 //in draw forall(pts,p, p:"trace"=p:"trace" ++ [p.xy] ); tr0=[[1,0],[0,1]]; tr1=[[-1,0],[0,1]]; tr2=[[-1,0],[0,-1]]; tr3=[[1,0],[0,-1]]; trs=[tr0,tr1,tr2,tr3]; forall(trs,t, forall(pts,p, connect((p:"trace")*t,color->p.color,size->2); ); ); //in init pts=allpoints(); forall(pts,p,p:"trace"=[]); 変数 "trace" に、自分自身の軌跡がどんどん追加されていくことを見てください。回帰直線すべての点に対する回帰直線を描きます。最小2乗法により正方形を描いていきます。 //in draw //Least-square line pts=allpoints(); m=apply(pts,(1,#.x)); y=apply(pts,#.y); ma=transpose(m)*m; mb=transpose(m)*y; mainv=inverse(ma); v=mainv*mb; f(x):=v_2*x+v_1; plot(f(x)); //Draw the squares sq(x,y1,y2):=( d=y2-y1; p=((x,y1),(x,y2),(x+d,y2),(x+d,y1),(x,y1)); drawpoly(p,color->(1,0.5,0.5),alpha->0.4); connect(p,color->(.8,0,0)); ); forall(pts,sq(#.x,#.y,(f(#.x)))); このコードでは、回帰直線を見つけるために高度な行列計算をしています。 ひまわりチュートリアルのひまわりよりちょっといい方法です。 //in draw n=round(100*|B,E|); d=0.01*(|D,F|/|D,C|-.5); ang=137.508°+d; repeat(n,i, w=ang*i; r=sqrt(i)*.2; p=(sin(w),cos(w))*r; draw(p,color->(1,0.8,0)); ); drawtext((-5,-6),"n="+n); drawtext((0,-6),"w="+180*ang/pi+"?"); このコードは、ヒマワリが成長するときに現れる特定の角度 ang=137.508deg. を用いています。関数プロット関数式を自由に入力してそのグラフを描きます。 //in draw //Parameter sliders a=K.x; b=L.x; c=M.x; d=N.x; drawtext(K+(0.2,0.2),"a="+a); drawtext(L+(0.2,0.2),"b="+b); drawtext(M+(0.2,0.2),"c="+c); drawtext(N+(0.2,0.2),"d="+d); //Parse and plot f(x):=parse(Text0.val); plot(f(x),color->red(0.6),size->2); 関数式は、シンデレラの文字入力ボタンで "Text0'' のところに書きます。これを直接解釈し、上のスライダできまる係数を使ってグラフを描きます。 色をまぜる3つの点A,B,Cを赤、緑、青の電球としましょう。この3つの色の混ざり具合をシミュレートします。 //in draw colorplot( (1-|#,A|/4, 1-|#,B|/4, 1-|#,C|/4), (-5,-5),(5,5),pxlres->3 ) このカラーミキサーは実に単純です。 colorplot 関数が、平面上の各点における色の混ざり具合を計算します。ジュリア集合フラクタルとして有名なジュリア集合です。複素数平面上の点Cが表す複素数によって計算されます。 //in draw g(z,c):=z^2+c; julia(z):=( iter=0; while(iter<100 & |z|<2, z=g(z,complex(C.xy)); iter=iter+1; ); 1-iter/100; ); colorplot(julia(complex(#)) ,A,B,startres->16,pxlres->1); ここでも colorplot 関数が大きな役割を果たします。上のコードで定義されている julia 関数は、各点の色を反復的に計算します。startres と pxlres 修飾子を使うことでより細かい図を描くことができます。群れのシミュレーション魚の群れをシミュレートします。それぞれの魚は隣の魚と同じ方向でしかもその場所に泳ごうとします。すべての魚は点Uによって与えられる障害を避けなければなりません。 //in draw ms=allmasses()--[U]; lim=0.5; apply(ms,m, near=select(ms,p,|p-m|<4); avg=sum(near,m,m.v)/length(near); m.v=m.v+.2*(avg); if(|m.v|>lim,m.v=lim*m.v/|m.v|) //Draw connections apply(near,draw(#,m,color->(0,0,0),alpha->0.2)); ); ここで、魚と障害物は正電荷を帯びた粒子としてモデル化されます。これにより、魚は互いに押しのけあいます。スクリプトはそれぞれの点の速度を設定します。
Contributors to this page: Akira Iritani
. The content on this page is licensed under the terms of the License. |
Login |