p5_underground

所謂クリエイティブコーディングとか音楽とかをぼちぼち楽しんでいきます

20180330_球を描く方法(球面座標系を使う)

ジェネラティブアートに出てくるやつ。説明になっているのかはわかりませんが、自分なりの理解で書いておきます。

 

まず球を三角関数で表現する数式がどっから出てきたのという感じなんですが、これです。

球面座標系 - Wikipedia

球面座標系。3次元空間上の任意の点を表すには、普通x, y, zの3つの座標を決めればいいんだけれど、それ以外の方法として、円柱座標系とかこれがある。平面でいうと、xyの直交座標の他に、極座標があるというのと同じ話。

 

Spherical with grid.svg
By Andeggs - 投稿者自身による作品, GFDL, Link

 

簡単に言うと、球面座標は、原点とその点とを結んだ線分の長さrと、その線分とz軸がなす角θと、その線分がxy平面につくる影とx軸とのなす角φを使って、3次元空間上の任意の点を表す方法です。3次元空間だしまあ3つのパラメータを固定してやれば1箇所に定まりますよね。で、これを直交座標に直すには次の式を使います。まあこれは当たり前というか、上の図を見ていけばすぐわかると思います。

x = r sinθ cosφ

y = r sinθ sinφ

z = r cosθ

 

ここでrが原点からの距離だったので、これを一定にして角度θとφはなんでもいいよ~としてやれば、これは球を表すことになりますね。これで本にでてくる公式になります。2つの角度θとφを決めてやれば、それに対応する球面上の点の座標がわかります。

 

じゃあこれを使って球を書いていく。サンプルだとθもφも同時に動かしているけど、たぶん片方固定しつつ片方動かしたほうが、公式の意味するところは分かりやすいはずなので、その方針でやっていきます。

 

2次元平面上で上から順に埋め尽くすように点を書いていくときには、xとyについて2重for文を書いて、2次元平面上を走査するということをしました。それと同様の要領で、角度θとφについての2重ループを作って、それぞれ0~360°の範囲を走査しつつ点を打っていけばいけるはず。

ということで、ジェネラティブアートのサンプルを少しいじって作ってみました。直観的にはθとφをforで変化させたかったけど、アニメーションにしたかったのでdrawループを使ってます。

import processing.opengl.*;

int radius = 100;
int phi = 0;
int theta = 0;
float lastx = 0; 
float lasty = 0;
float lastz = 0;

void setup() {
  size(500, 300, OPENGL);
  background(0);
  stroke(255);
} 
  
void draw() {
  translate(width/2, height/2, 0);  
  rotateX(radians(45));
  rotateY(radians(30));

  float radianPhi = radians(phi);
  float radianTheta = radians(theta);
     
  float thisx = 0 + (radius * cos(radianPhi) * sin(radianTheta));
  float thisy = 0 + (radius * sin(radianPhi) * sin(radianTheta));
  float thisz = 0 + (radius * cos(radianTheta));
     
  if (lastx != 0) {
    line(thisx, thisy, thisz, lastx, lasty, lastz);
  }
  lastx = thisx; 
  lasty = thisy; 
  lastz = thisz;

  phi += 10;
  if(phi == 360){
    theta += 10;
    phi = 0;
  }

}

見やすいように回転させてますが、さっきの球面座標でいうと、開始点である球のてっぺん方向がz軸の正の向きで、1段下にずれるところがx軸の正の向きということになりますね。φを0~360°で1周させて、360°になったらθを10°ずらしてφはリセット、また1周させて...というように動かしています。

 

以上。