マウスでシミュレーション制御(工事中)
以下の解説は私の
カスタマイズ用ファイルの使用を前提とします。
- 使い方は非常にシンプル!:
⇒ for文やwhile文の最後に "if(idl(パラメータ))break;" と書くだけ.
- yorickの描画関数は高速なので数値計算と同時に描画しても速いです.
制御関数の説明
・
idl
使用例
・
単純な例
・
2次元の例
・
3次元の例
・
反応拡散方程式
idl:制御関数
idl(dp,count,rot=,flag_stop=,fun1=,fun2=,arg1=,arg2=)
- dp: スピード調節のために毎回行う一時停止(整数:ミリ秒)
- count: カウント(整数)
- rot=: 3D描画物の回転操作をするか(0/1)
- fun1=:登録関数(引数はarg1)
- fun2=:登録関数(引数はarg2)
- fun3=:登録関数(引数はarg3)
基本操作
- スタート/一時停止:メニュー1番目の左クリック(またはCtrl+右クリック)
- 終了:メニュー1番目の右クリック
- 移動:左ドラッグ
- 拡大:左クリック
- 縮小:Shift+左クリック
- 回転:右ドラッグ(rot=1の場合のみ)
- 一時停止中の角度の変更:Ctrl+左ドラッグ(rot=1の場合のみ)
補足1:コマンド実行(メニューの"command"をクリック)
fun3に何も指定しない場合、デフォルトのidl_fun3という関数が実行されて、"Enter command:"というプロンプトが表示されるので、任意のコマンドを実行できます。
グローバル変数nlevsの値を変更する例:
Stop
"fun2"
Enter command: extern nlevs; nlevs=5;
他にも例えば、グラフを画像として保存(outpng)、パレットを変える(pal)、他の関数を実行、などができます。
補足2:回転モード(メニューの"RoAxis"を左クリック)
回転モードは①自由な回転」と②x,y,z軸のいずれかを回転軸とする回転、の2種類あります。
②の場合は、回転軸にしたい軸と垂直な方向に左ドラッグすると、その軸を回転軸として描画物が回転します。
補足3:仕組み
関数の実行中はプロンプトへの入力はできませんが、マウスの左クリックや右クリックによる描画物の拡大・縮小の操作は反映されます(グラフィクスが独自のイベントループを持っている)。
すなわち、実行中の関数が描画領域のx,y座標の変化をチェックすることで、マウスクリックに対応して一時停止できます。
一時停止できれば後はマウスやキーボードからの入力を得て色んなことができます(グラフィクスのイベントループに自分の計算を埋め込む感じになります)。
単純な例
- include,"idl_demo0.i" で実行できます。
- 基本的には繰り返し構文(for文やwhile文)を閉じる"}"の直前にidl関数をセットするだけです。
- line_colorはグローバル変数なので計算途中でも変更できます。(メニューの"コマンド"をクリックして"Enter command:"を表示させて、"extern line_color; line_color=blue;"と入力して一時停止を解除すると線の色が変わります。)
line_color=red;
idl_init_pause=1;
idl_init=1;
x=span(0,12,100);
win2;
animate,1;
for(i=0;i<=10000;i++){
fma;
plg,sin(i*0.05+x)+cos(-i*0.08+1.5*x+1),x,color=line_color;
if(idl(20))break;
}
animate,0;
補足
for文の前のanimate,1と終了後のanimate,0はアニメーションモードのオンオフです。必須ではありませんが、画面のチラつきを防ぐことができます。
2次元の例
- include,"idl_demo1.i" で実行できます。
- 2次元座標(x,y)上の値zを時間変化させて、plfcで描画しています。
- idlの引数fun1、fun2にfunction1とfunction2を指定しており、メニューのfun1/2のボタンの左クリックと右クリックで等高線の数を増やしたり減らしたりできます。
- "command"をクリックして"extern nlevs; nlevs=5;"でも変更できます。
func function1(void){
extern nlevs;
nlevs=nlevs+1;
write,"Contours are increased to:",nlevs;
}
func function2(void){
extern nlevs;
nlevs=nlevs-1;
write,"Contours are decreased to:",nlevs;
}
nlevs=10;
func idl_demo1(dp){
if(is_void(dp))dp=20;
extern nlevs;
x= span(-3,3,64)(,-:1:64);
y= transpose(x);
z= sin(2*sqrt(x^2+y^2))+cos(x+y+0.13);
animate,1;
for(t=0;t<=10000;t++){
z= sin(2*sqrt(x^2+y^2)+0.02*t)+cos(x+y+0.013*t);
fma;
levs=span(-1.5,1.5,nlevs);
plfc,z,y,x,levs=levs;
plc,z,y,x,color=red,levs=levs;
// cbfc,[-2,2],levs=levs,ticks=1,label=1;
xyt,"x","y";
redraw;
if(idl(dp,fun1=function1,fun2=function2))break;
}
animate,0;
}
win2;
idl_init=1;
idl_demo1,10;
3次元の例
- include,"idl_demo2.i" で実行できます。
- 2次元座標(x,y)上の値zを時間変化させて、pl3surfで描画しています。
- idlのrotが1なので、右ドラッグで描画物を回転できます。
- メニューの"RoAxis"の左クリックを繰り返すと回転モードを変更できます。
func idl_demo2(void){
x= span(-3,3,32)(,-:1:32);
y= transpose(x);
z= sin(2*sqrt(x^2+y^2))+cos(x+y+0.13);
make_xyz,z,y,x,nv,xyzv;
pl3surf,nv,xyzv;
lim3,3,3,6;
cage3,1;
orient3;
setz3,7;
limits;
draw3,1;
scale,0.9;
animate,1;
for(t=0;t<=3000;t++){
xyzv(3,)= sin(2*sqrt(xyzv(1,)^2+xyzv(2,)^2)+0.2*t)+cos(xyzv(1,)+xyzv(2,)+0.13*t);
pl3surf,nv,xyzv;
lim3,3,3,6;
draw3,1;
if(idl(20,t,rot=1))break;
}
animate,0;
}
idl_rotation=2;
idl_rotation_speed=[0,0,0.003];
win2,offset_w=100;
win3;
idl_init=1;
idl_init_pause=1;
idl_demo2;
反応拡散方程式の例
- include,"idl_demo3.i" で実行できます。
- 2次元座標上のgray-scottモデル(熱帯魚の模様とかを説明できるモデル)の2つの成分のうちの片方の濃度をplfcで描画しています。
func function1(void){
cpal=["earth","heat","sunrise","bb","cr"];
id=1;
n=read(prompt="Choose palette: 1: earth, 2: heat, 3: sunrise, 4: bb, 5: cr >",id);
pal,cpal(id);
}
size = 120;
dt =0.2;
view_interval=100;
count_interval=1000;
a = 0.023;
b = 0.055;
gridx=span(0,1,size)(,-:1:size);
gridy=transpose(gridx);
dif_gridx=span(0.3,2.0,size)(,-:1:size);
dif_gridy=transpose(dif_gridx);
dif_rate_x = (8.0e-2)*dif_gridx;
dif_rate_y = (4.6e-2)*dif_gridy;
x=array(1.0,size,size);
y=array(0.001,size,size);
y(size/2,size/3) = 0.5;
diffuse_mask=grow(1,indgen(size),size);
func idl_demo3 (T,dp=){
if(is_void(T))T=10000;
if(is_void(dp))dp=1;
fma;
plfc,y,gridy,gridx,levs=spanl(0.05,0.6,20);
xyt,"Diffusion rate for x", "Diffusion rate for y";
limits;
animate,1;
for(t=0; t<=T;t++){
diffuse_x=(x(,diffuse_mask)(,dif)(,dif)+x(diffuse_mask,)(dif,)(dif,));
diffuse_y=(y(,diffuse_mask)(,dif)(,dif)+y(diffuse_mask,)(dif,)(dif,));
x += dt*(-1.0*x*y*y + a*(1.0-x) +dif_rate_x*diffuse_x);
y += dt*(x*y*y - (a+b)*y+dif_rate_y*diffuse_y);
if(t%count_interval==0)t;
if(t%view_interval==0){
fma;
plfc,y,gridy,gridx,levs=spanl(0.05,0.6,20);
xyt,"Diffusion rate for x", "Diffusion rate for y";
if(idl(5,fun1=function1))break;
}
}
animate,0;
}
win2,500,500;
idl_init_pause=1;
idl_init=1;
idl_demo3,100000;