領域表示
簡単な領域表示 正負で色分け
f(x,y)=が正の部分と負の部分を色分けして図示したい。
描画領域の全てのピクセルで値を計算すれば出来るけども、それじゃ芸が無いから別の方法を試す。
演算子の再定義
実数の四則演算(実数×実数→実数)を、範囲の演算(範囲×範囲→範囲)に変更する。ある範囲でのf(x,y)値の正負を一度に評価して計算量削減できるはず。
例
[3〜4]+[10〜20]=[13〜24]
[5〜8]×[-1〜2]=[-8〜16]
コードにするとこんな感じ
function add(x,y){return [x[0]+y[0],x[1]+y[1]];} function sub(x,y){return [x[0]-y[1],x[1]-y[0]];} function mult(x,y){ var e,a=x[0]*y[0],b=x[0]*y[1],c=x[1]*y[0],d=x[1]*y[1]; if(a>b){e=a;a=b;b=e;}if(c>d){e=c;c=d;d=e;} return [a<c?a:c,b<d?d:b]; }
これを使って、f(x,y)を書き換える。
演算子オーバーロードが使えたら楽なんだけど・・・
//function f(x,y){return x*x*x+y*y*y-xy} function func(x,y){ var xxx=mult(x,mult(x,x)); var yyy=mult(y,mult(y,y)); var xy=mult(x,y); return sub(add(xxx,yyy),xy); }
このfuncはf(x,y)の範囲(値域)をゆるーく評価する関数になってる。
描画手順
1. ある広い領域x,yでfunc(x,y)を実行2. 必ず正もしくは必ず負になるのなら色を塗って終わり
3. 正負判別できない時は、4分割した小さい領域で同じ操作をする
コード全体
<script> function add(x,y){return [x[0]+y[0],x[1]+y[1]];} function sub(x,y){return [x[0]-y[1],x[1]-y[0]];} function mult(x,y){ var e,a=x[0]*y[0],b=x[0]*y[1],c=x[1]*y[0],d=x[1]*y[1]; if(a>b){e=a;a=b;b=e;}if(c>d){e=c;c=d;d=e;} return [a<c?a:c,b<d?d:b]; } function func(x,y){ var xxx=mult(x,mult(x,x)); var yyy=mult(y,mult(y,y)); var xy=mult(x,y); return sub(add(xxx,yyy),xy); } function start(){ var canvas=document.getElementById("canvas"); var context=canvas.getContext("2d"); var queue=[[0,0,512]],index=0; function recursive(x,y,s){ var xx=2*x/512-1,yy=1-2*y/512,d=2*s/512; var z=func([xx,xx+d],[yy-d,yy]); if(z[1]<0)context.fillStyle="red"; else if(z[0]>0)context.fillStyle="blue"; else{ if(s!=1){ queue.push([x,y,s/2]); queue.push([x+s/2,y,s/2]); queue.push([x,y+s/2,s/2]); queue.push([x+s/2,y+s/2,s/2]); } var c="0123456789abcdef",zm=-z[0]+1e-16,zp=z[1]+1e-16,zz=zm+zp; context.fillStyle="#"+c.charAt(parseInt(16*zm/zz))+"0"+c.charAt(parseInt(16*zp/zz)); } context.fillRect(x,y,s,s); } function loop(){ for(var i=0;i<256;i++){ var p=queue[index++]; if(!p)return; recursive(p[0],p[1],p[2]); } setTimeout(loop,0); } loop(); } </script> <body onload="start()"> <canvas width=512 height=512 id="canvas">
簡単な構文解析っぽいのを付けたサンプル
http://www.geocities.jp/flyinpng/calc20110528/
特徴
・計算完了する前に概形が見える
・計算オーダーはだいたいピクセル数の平方根に比例
・けどそこまで速くなくてしらみつぶしのほうがましな場合も
いつかどこかで何かに使えるかも。