RSS

 

RSS


パ:球表面に乱数で点を打つには

  • いわいまさか
  • at 2014/5/23 15:22:03

パズル懇話会で
「球の表面に乱数で点を打つには?」
というのを話題にした。
「3D的に偏りなく打ちたい」。

自分なりの答えを持っていったが、メンバーからいろんな方法を聞いたのでそれをメモ。

(1) 立方体にうってからの

「平面で円の中に乱数をうつときの方法」を話していて、
そこからの流れで白川さんが言及

球が内接する立方体に乱数で点をうつ
球の中に入っているものだけ採用
球の表面に乗るように射影(正規化)する

Retry:
x=rand();    // -1.0~1.0 の乱数
y=rand();
z=rand();
if(x*x+y*y+z*z<=1.0){
   // 採用
 //  中心から球への射影
 //  あるいは半径1への正規化
  r=sqrt(x*x+y*y+z*z);
  rr=1.0/r;
  x=x*rr;
  y=y*rr;
  z=z*rr;
}else{
   goto Retry;  // やりなおし 捨てる
}

長所:わかりやすい。<<<<<<<<<<<<<<<<<<<<<<<
短所:乱数の振りなおしがある。

(2)正規分布乱数を使っての

  飯田さん案。

  正規分布を使う。

   x=正規分布乱数(); // 0を中心とした正規分布
    y=正規分布乱数();
  z=正規分布乱数();

  // 球の表面にのせる
   r=sqrt(x*x+y*y+z*z);
   rr=1.0/r;
   x=x*rr;
   y=y*rr;
   z=z*rr;

  「x,y,zがそれぞれ正規分布だった場合
  3次元としての(x,y,z)も正規分布」なのだと<<<<<<<<<<<
  白川さんや飯田さんがそのように言っていた。

長所:乱数振りなおしがない
短所:正規分布乱数を持ってる必要がある

(3) いやいやそんなことしなくても

 岩沢さんが示してくれた方法
  緯度と経度で考えて

 緯度方向の高さ
 z=rand();       <<<<※

  経度方向の角度で
 theta=rand()*PI
  x=cos(theta);
  y=sin(theta);

 で完了だとのこと。

 ※のところは
  「球の表面積と円柱の側面の表面積が同じ」あたりと関係している。

長所:乱数2回で捨てるとこなし。
短所:zとx,yの取り扱いが違うところが数値計算的にはいくらか心配。

↓wolframalphaで描いた球

以上


  • コメント (1)
  • トラックバック (0)
トラックバックURL :
http://www.iwai-masaka.jp/tb.cgi/56085

コメント

x,yはsqrt(1-z^2)の掛け算が抜けているのでは?