2012-03-20 127 views
1

如何計算球體周圍的點數?我需要這個用於我的粒子爆炸。我不希望粒子的點都是隨機的。我需要它們的球形圖案。 對於2D圈爆我用的是這樣的:計算球體周圍的點數

float n=many; 
float rad = 1; 
for (int i = 0; i < n; i++) 
{ 
     float fi = 2*PI*i/n; 
     float x1 = rad*sin(fi + PI)+x ; 
     float y1 = rad*cos(fi + PI)+y ; 
     addparticlesmart(x,y,(x1-x),(y1-y), 0.01f),r,g,b,a,0.02f); 
} 
+4

http://www.cs.cmu.edu/~mws/rpos.html – Bart 2012-03-20 13:20:41

+0

IMO最簡單的方法是生成高斯分佈的_x_,_y_,_z_值,並將矢量歸一化到所需的半徑。 – leftaroundabout 2012-03-20 13:24:44

+0

@Bart:這不會給球體上的均勻分佈(其中每個區域元素將獲得相同的密度) – leftaroundabout 2012-03-20 13:26:52

回答

5

您有幾種選擇。

緯度/經度 - 遍歷從緯度 - 從0 π/2到+ π/2和經度爲2 π在你喜歡的任何時間間隔。然後從球面座標轉換爲笛卡爾座標。雖然這很容易編碼,但它的缺點是這些點往往集中在兩極。

鑲嵌 - 你可以選擇一個regular polyhedron,最好用三角形面,(一個icosahedron是我最喜歡的了)和遞歸地找到每個面的每個邊緣的角平分線。然後,將該面分成四個三角面,將平分點歸一化,使它們位於球面上。雖然這些點不是很均勻地分佈在球體上(如果不使用二十面體作爲基底多面體,可以看出它看起來比緯度/經度方法更均勻分佈)。它有一個缺點,編碼更難。更詳細的描述可在here獲得。

隨機點 - 我知道你說你不喜歡挑選隨機點的想法,但爲了完整性我會在這裏包含它。在Wolfram's site有一個很好的治療。

+0

我看到了wolfram的網站。但是我沒有看到計算theta和phi並將它連接到中心點和半徑以便在球體中產生隨機點之間沒有關係。 我不知道如何將其轉換爲代碼。我有我的theta,我有我的phi。我如何獲得具有x,y,z座標和R半徑的球體上的點的座標? – 2017-10-09 07:43:57

+1

@JohnDemetriou這是一個不同的問題。您需要在笛卡爾座標和Spherial座標之間轉換(https://www.google.com/search?q=cartesian+to+spherical&oq=cartesian+to+sph&gs_l=psy-ab.3.0.0l10.5531.6540.0.7737.3.3。 0.0.0.0.330.874.2-2j1.3.0 .... 0 ... 1.1.64.psy-ab..0.3.872 .... 0.4Swcsyj5ArA),反之亦然。 – andand 2017-10-09 15:07:02

+1

@JohnDemetriou爲了完整......這裏是將球面座標轉換爲笛卡爾座標的主題(https://www.google.com/search?q=spherical+to+cartesian&oq=spheric&gs_l=psy-ab.3.0.0i20i263i264k1j0i67k1l6j0l3.87228.88833。 0.90803.7.7.0.0.0.0.289.784.0j2j2.4.0 .... 0 ... 1.1.64.psy-ab..3.4.782 ... 46j35i39k1j0i20i264k1j0i46k1.0.Tv9yinF4kYc)。 – andand 2017-10-09 15:13:29

6

從球形完全轉化成直角座標:

Cartesian coordinates: (x,y,z) 
Spherical coordinates: (r,φ,θ) with r∈[0,∞), φ∈[0,2π), θ∈[0,π] 

Then: 
x = r*cos(φ)*sin(θ) 
y = r*sin(φ)*sin(θ) 
z = r*cos(θ) 
+0

正確,但您還需要考慮座標映射的差異以在球體上產生適當的概率密度。 – leftaroundabout 2012-03-20 13:28:40

+0

我只是指出了它背後的數學。實際的實現類似於提問者對於二維情況的實現,實際上很簡單:您只需將所有內容放在另一個地方,以便類似地計算'θ'(btw'z'以及它不受影響從φ的值開始,使用我提供的符號)。然後你可以相應地修改給定'for'中的代碼,即乘以'sin(θ)'。當然,你必須考慮的是你真正需要的東西。 – 2012-03-20 13:36:22

3

如果你可以使用新的C++ 11標準,很容易創建高斯分佈的隨機數。然後可以使用三個一維高斯數作爲一個三維高斯座標的事實,該三維高斯座標均勻分佈在恆定半徑的球體上(半徑爲高斯分佈)。如果您只需要在特定半徑上的座標,則必須標準化座標。這裏是你如何能做到這一點:

#include <iostream> 
#include <random> 
#include <cmath> 


using namespace std; 

int main (int argC, char* argV[]) 
{ 
    //Create random generator 
    mt19937 rnd; 
    //Create Gaussian distribution 
    normal_distribution<double> normDist (0.0, 1.0); 
    //Seed random generator 
    rnd.seed(time(NULL)); 

    const double sphereRadius = 1; 

    //Create 3 Gauss Random Numbers 
    double rndArray[3]; 
    double rndSqrSum = 0; 
    for (uint i = 0; i < 3; i++) 
    { 
     rndArray[i] = normDist(rnd); 
     rndSqrSum += rndArray[i] * rndArray[i]; 
    } 

    //Calculate Faktor to get a Sphere of radius sphereRadius 
    double faktor = sphereRadius/sqrt(rndSqrSum) ; 

    //The random Coordinates then are: 
    double x = rndArray[0]*faktor; 
    double y = rndArray[1]*faktor; 
    double z = rndArray[2]*faktor; 

    cout << "Koordinates are: " << endl << "x: " << x << endl << "y: " << y << endl << "z: " << z << endl << "Radius is: " << sqrt(x*x+y*y+z*z) << endl; 

} 

爲您的應用程序可能不需要,但有用的,可以用於任意尺寸的這種方法,例如: 20維問題。