特性関数の可視化

多くのレイトレーシングの仕組みの概要:出力ウィンドウ内の各ピクセルを介して、アルゴリズムはビームを通過させ、シーン内で交差するオブジェクトと、結果としてピクセルを照らす方法を計算します。 アルゴリズムでは、各位置に対してポイントの色を返す関数が必要です。 もちろん、同じアプローチは3次元グラフィックスだけでなく適用できます。適切な機能があれば、この方法で任意の画像をラスタライズできます。 たとえば、このアプローチを使用して、 helarqjsc記述した 単純な分解図を視覚化する問題を解決する方法を考えてください



私の実装はこちらです。 写真は10を示しています! =3628800。ただし、すべての詳細はもちろん表示されません。



この問題では、他の多くの場合と同様に、色は二値化されます:黒または白。 したがって、関数check(x、y)の形式の関数が必要です。この関数は、指定されたポイントをペイントするかどうかを示す論理値を返します。 数学者は、check(x、y)は平面上の点の集合の特徴的な関数であると言うでしょう(数学では、このような関数は通常1または0を返します)。 この関数を指定すると、HTML5 Canvasの描画アルゴリズムは非常に簡単になります。

function trace(canvas) { var ctx = canvas.getContext("2d"); var w = canvas.width; var h = canvas.height; var img = ctx.createImageData(w, h); for(var x=0; x<w; x++) for(var y=0; y<h; y++) if(check(x,y)) img.data[(y*w+x)*4+3]=255; ctx.putImageData(img, 0, 0); }
      
      





ここでは、createImageDataが黒い透明なキャンバスを作成するという事実を利用しています。 透明性の原因となるバイトのみを変更します。



たとえば、中心(50、50)と半径50の円を描くと仮定します。チェック(x、y)関数は次のようになります。

 function check(x,y) { return (x-50)*(x-50)+(y-50)*(y-50)<50*50; }
      
      



中心からの距離の二乗の合計は、半径の二乗より小さい。 次の図が表示されます。



もちろん、サークルの場合、ライブラリ機能を使用する方が簡単で安価です。 さらに、私たちの円は角張っていることになりました。 これを少し克服するために、サブピクセルレンダリングを使用します。ピクセルをn×n個の小さいピクセルに分割し、それぞれに対してcheckを実行し、成功したチェックの数に比例して透明度を設定します。

 function trace(canvas) { var ctx = canvas.getContext("2d"); var w = canvas.width; var h = canvas.height; var img = ctx.createImageData(w, h); var n = 2; for(var x=0; x<w; x++) for(var y=0; y<h; y++) { var k=0; for(var xx=0; xx<n; xx++) for(var yy=0; yy<n; yy++) if(check(x+xx/n, y+yy/n)) k++; if(k) img.data[(y*w+x)*4+3]=255*k/n/n; } ctx.putImageData(img, 0, 0); }
      
      





結果は次のとおりです。



すでにかなり美しいです。 いくつかの場合、nの値を増やすことができます(もちろん、カウントが遅くなります)。



元の問題に戻りましょう。 基本的に、素因数分解図の特性関数を書く必要があります。 関数のプロトタイプを少し変更して、タスクに必要なすべてのパラメーターを渡し、再帰を利用します。 check関数は引数(factors、n、x、y、r)を取ります。xとyは円の中心に対する点の座標、rは円の半径、factorsは素因数の配列です。helarqjscのように、2つはすでに4つに結合されています。 nは、検討を開始する必要がある配列の要素です。 チェック機能は次のようになります。

-中心から現在のポイントまでの距離が半径よりも大きい場合、ポイントは正確に適合しません-falseを返します。

-nが配列の最後を指している場合、最後に到達し、塗りつぶされた円を描く必要があります。trueを返します。

-それ以外の場合、次の次数(r1)の円の半径を計算します。

-中心から現在のポイントまでの距離が半径から新しい円の直径を引いた値(2 * r1)より小さい場合、ポイントはリング内に収まります-falseを返します。

-ポイントが属するセクターを計算します(図のグレー)。

-私たちは同じファクターで、より大きなn、新しい半径r1、xとyの値を、新しい円の中心に合わせて調整して呼び出します。



実際、それがすべてです。 完成したアプリケーションは、JSでここで確認できます (ブラウザでキャンバスのサポートが必要です。IE6-8のフォールバックはありません)。 helarqjsc関数を使用してファクタリングしましたが、レンダリングは完全に私のものです。 円の半径とセクターの位置を異なる方法で計算したため、私の写真は少し異なります。 レンダリング速度が実際に入力数に依存しないことに気付くかもしれません。 helarqjscの実装は最初の100の方高速ですが、その後、私のものが勝ち始めます(正直なところ、サインとコサインの値もキャッシュしませんでした)。 私が使用したアプローチにより、多くの重要なものの視覚化を単純化および高速化できます。 フラクタルをレンダリングするときに特に役立ちます。 また、私のアプローチでは、写真の任意の領域に無制限のズームを追加するのは非常に簡単です。



All Articles