ブラウン運動の可視化プログラムを少し改造してみた

はじめに

光栄なことに、昨日のエントリに対し、結城浩さんからコメントを頂きました。


それを見て「よっしゃ、作ってみるか」となった次第です。

とりあえずHTML5で二次元のものを作ってみました。

実行結果

これが今回作ったもの。bias機能は取り除きました。

http://gachapin.jp/brown2d_2.html

前回作ったものがこちら。

http://gachapin.jp/brown2d.html

比較すると、動きが艶かしくリアルになった気がします。

結晶中の電子の動きの再現という点では、前回のモデルと今回のモデルのどちらがより良いモデルなんでしょうか?

ソースコード

ソースコードGoogle codeでダウンロードできます。


差分を中心に。

... snip ...

var sin_table ;
var cos_table ;

... snip ...
 
var Electron = {
 
  x: Width / 2,
  y: Height / 2,
 
  checkConstraint: function( ) {
 
    if( this.x > Width )
      this.x -= Width ;
    if( this.x < 0 )
      this.x += Width ;
    if( this.y > Height )
      this.y -= Height ;
    if( this.y < 0 )
      this.y += Height ;
 
  },
 
  getRandom: function( ) {
    return parseInt( Math.random( ) * 360 ) ;
  },
 
  move: function( ) {
 
    var r = this.getRandom( ) ;
    this.x += cos_table[ r ] ;
    this.y += sin_table[ r ] ;
 
    this.checkConstraint( ) ;
 
  },
 
  beRandom: function( ) {
    this.x = parseInt( Math.random( ) * Width ) ;
    this.y = parseInt( Math.random( ) * Height ) ;
  },
 
  display: function( ) {
    surface.drawImage( img, this.x - 1 , this.y - 1) ;
  }
 
} ;
 
function init( ) {
 
  surface = document.getElementById( "canvas" ).getContext( "2d" ) ;
  initTable( ) ;
  initImage( ) ;
  initElectrons( ) ;
 
}
 
function initTable( ) {
 
  sin_table = new Array( ) ;
  cos_table = new Array( ) ;
 
  for( var i = 0; i < 360; i++ ) {
    sin_table.push( Math.sin( i / 180 * Math.PI ) ) ;
    cos_table.push( Math.cos( i / 180 * Math.PI ) ) ;
  }
 
}

... snip ...

毎回sin, cos計算をさせるのが嫌だったので、最初にsin, cos計算結果をテーブルに格納してそれを使うようにしました。

drawImage( )は座標に小数を入れています。小数を使うと表示速度が遅くなるという話を聞きましたが、どんなもんでしょうか。

こぼれ話

この実装はすぐに思いついたのですが、以下の懸念点がありました。

  1. 小数の演算を繰り返すので計算誤差が蓄積される(含むsin, cos計算の打ち切り誤差)
  2. 毎回sin, cos計算を行うことによる処理速度の劣化
  3. drawImage( )が少数の座標を受け入れてくれるか


そんなわけで、何かしら工夫すれば小数を使わなくても計算できるのでは?と考えてみたのですが思いつかず。メンバ変数にx, yではなくr, θを持たせようかとか考えたのですが、かえって計算が面倒になりそうだったのでやめました。

2. は計算結果をテーブルに入れておくことで対処が可能でしたし、3. は調べたら処理が遅くなるものの可能なことがわかりました。

javascriptの小数の内部表現がどうなっているか知らないので1.は気になっていたのですが、とりあえず作って動かしてみたらそんなに悪くなかったので、これで完成にしました。

終わりに

アルゴリズムを工夫してもっと面白い実装をしたかったのですが、無難な感じになりました。

改良ポイントはいくつかあると思っているので、思いついたら更新しようと思います。

C++版、三次元版も後日作ってみようと思います。