そら飛ぶタピオカ

メディアアートネタとかを書きます

球表面・球内に一様分布する点をいっぱい生成する

球表面・球内に一様分布する点の生成方法を調べたのでメモ。
下記のページを参考にしました。
球面上にランダムで置いたプロットをなるべく分散させたい - Qiita
http://apollon.issp.u-tokyo.ac.jp/~watanabe/pdf/prob.pdf

球表面に一様分布する点

単位球表面に一様に分布する点の座標  (x, y, z) は、2つの一様乱数

{
\begin{eqnarray}
\left\{ \begin{array}{ll} 
  z & (-1 \leq r \leq 1) \\
  \phi & (0 \leq \phi < 2 \pi) 
\end{array}\right.
\end{eqnarray}
}

を用いて、

{
\begin{eqnarray}
\left\{ \begin{array}{ll}
  x = \sqrt{1-z^2} \cos \phi \\
  y = \sqrt{1-z^2} \sin \phi \\
  z = z
\end{array}\right.
\end{eqnarray}
}

で求められます。
任意の半径の球を考える場合は、各座標に半径をかければ求められます。

球内に一様分布する点

単位球内に一様に分布する点の座標  (x, y, z) は、3つの一様乱数

{
\begin{eqnarray}
\left\{ \begin{array}{ll} 
  z & (-1 \leq r \leq 1) \\
  \phi & (0 \leq \phi < 2 \pi) \\
  r & (0 \leq r \leq 1)
\end{array}\right.
\end{eqnarray}
}

を用いて、

{
\begin{eqnarray}
\left\{ \begin{array}{ll}
  x = r^{1/3} \sqrt{1-z^2} \cos \phi \\
  y = r^{1/3} \sqrt{1-z^2} \sin \phi \\
  z = r^{1/3} z
\end{array}\right.
\end{eqnarray}
}

で求められます。
球表面と同様に任意の半径の球を考える場合は、各座標に半径をかければ求められます。

実際に生成してみる

openFrameworksで実際に生成してみるとこんな感じになります。
緑の点が球表面、赤の点が球内に一様分布する点になります。
ちゃんと一様に分布してるっぽい。
f:id:tapioca24:20170219010351g:plain

ofApp.h

#pragma once
#include "ofMain.h"

class ofApp : public ofBaseApp{
public:
  void setup();
  void draw();
  
  ofEasyCam cam;
  ofMesh mesh;
  int num; // 頂点数
  float radius; // 半径
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
  ofBackground(0x32);
  ofEnableDepthTest();
  cam.setDistance(480);

  num = 2000;
  radius = 200;
  
  // 球表面に一様な分布する点を生成
  for (int i = 0; i < num; i++) {
    float z = ofRandom(-1.0, 1.0);
    float phi = ofDegToRad(ofRandom(360));
    float x = sqrt(1 - z * z) * cos(phi);
    float y = sqrt(1 - z * z) * sin(phi);
    mesh.addVertex(radius * ofVec3f(x, y, z));
    mesh.addColor(ofColor::fromHsb(100, 200, 250));
  }
  
  // 球内に一様に分布する点を生成
  for (int i = 0; i < num; i++) {
    float r = ofRandom(1.0);
    float z = ofRandom(-1.0, 1.0);
    float phi = ofDegToRad(ofRandom(360));
    float x = cbrt(r) * sqrt(1 - z * z) * cos(phi);
    float y = cbrt(r) * sqrt(1 - z * z) * sin(phi);
    z = cbrt(r) * z;
    mesh.addVertex(radius * ofVec3f(x, y, z));
    mesh.addColor(ofColor::fromHsb(240, 200, 250));
  }
}

//--------------------------------------------------------------
void ofApp::draw(){
  cam.begin();
  ofRotate(ofGetElapsedTimef()*10, 1, 1, 0);
  glPointSize(4.0);
  mesh.drawVertices();
  cam.end();
}

openFrameworksプロジェクトをGitでバージョン管理

openFrameworksのプロジェクトをGitでバージョン管理しようとしたとき、どのファイルを追跡対象にすべきなのか迷っていたら下記のページに解説が載っていたのでメモ。
ofBook - Version control with Git
このページには他にもグラフィック関連だったりC++関連だったりの基礎的なところから充実した解説が載ってるので重宝しそうです。

手順

まずは普通にprojectGeneratorで空のプロジェクトを作成します。
次にプロジェクトフォルダへ移動してGitリポジトリを生成します。

$ git init

次に、.gitignoreファイルを作ります。
プロジェクトをビルドして生成されるバイナリファイルや、IDEの設定ファイル、OSによって生成されるバックアップファイル等は追跡不要なので、それらを.gitignoreに指定して追跡対象から除外します。
将来的にはprojectGeneratorで自動的に.gitignoreを作ってくれるようになる予定のようですが、現在は下記のページで公開されているテンプレートを使用すると良いでしょう。
github.com

内容はこんな感じで、binフォルダ以下のファイル(bin/dataフォルダを除く)、各IDEやOSごとの追跡不要ファイル拡張子などが指定してあります。

#.gitignore is a file which makes git ignore files which should
# not go into version control in the first place
# Questions? See
# http://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files
# http://git-scm.com/docs/gitignore

###########################
# ignore generated binaries
# but not the data folder
###########################

/bin/*
!/bin/data/

#########
# general
#########

[Bb]uild/
[Oo]bj/
*.o
[Dd]ebug*/
[Rr]elease*/
*.mode*
*.app/
*.pyc
.svn/
*.log

########################
# IDE files which should
# be ignored
########################

# XCode
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
# XCode 4
*.xccheckout
xcuserdata/

# Visual Studio
*.sdf
*.opensdf
*.suo
*.pdb
*.ilk
*.aps
ipch/

# Eclipse
.metadata
local.properties
.externalToolBuilders

# Android Studio
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries

##################
# operating system
##################

# Linux
*~
# KDE
.directory
.AppleDouble

# OSX
.DS_Store
*.swp
*~.nib
# Thumbnails
._*

# Windows
# Image file caches
Thumbs.db
# Folder config file
Desktop.ini

# Android
.csettings

基本的にはこれを使用し、必要があれば追記する形で問題ないでしょう。

/bin/data/以下の特定フォルダを追跡対象から除外したい場合

/bin/*
!/bin/data/

となっているので、/bin/data/フォルダは追跡対象です。
ですが、/bin/data/フォルダはデバッグ用の画像を出力したりしたいときがあります。
その場合、例えば以下を加えることで特定のフォルダを追跡対象外にできます。

/bin/*
!/bin/data/
/bin/data/export/

これで/bin/data/export/フォルダは追跡対象外となるので、Gitで追跡したくないファイルはここへ書き出すよう運用すればOKです。


あとは普通にGitを使用すれば良いでしょう。

$ git add .
$ git commit -m "Initial commit"

IDEが生成するファイルって何のためのファイルなのか全然分からないんですよね〜。
テンプレート万歳!!