2010-12-03 130 views
3

我很感興趣的是生成一致地(和非隨機地)分佈在球體周圍的點,就像高爾夫球的凹坑或足球上六邊形的頂點。是否有明確的算法來做到這一點?在球體上均勻地生成點

注意:我知道這些點並不是真的「均勻」分佈在一個球體上,但它們的分佈方式使點的分佈看起來與從任何一點直接看到的任何方向相同 - 這是我所感興趣的。

+3

以下是相應的[Google搜索](http://www.google.com/search?q=distribute+points+on+a+sphere&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla: DE-DE:非官方&客戶= iceweasel-A)。第一個命中甚至包括C++和Java中的實現。 – 2010-12-03 20:51:15

+0

我不知道在你的意義上,統一分佈任意數量的點。高爾夫球上的凹痕數量是固定的(儘管我不記得數字),足球上六角形頂點的數量也是如此。 – 2010-12-03 20:54:58

回答

1

細分一個八面體,然後正常化頂點給出了非常好的結果。 Look here瞭解更多詳情。保羅·伯克有很多有趣的東西。

下面是一些僞C++代碼,我在五分鐘內寫了現在:

/* Assume 'data' initially holds vertices for eight triangles (an octahedron) */ 
void GenerateSphere(float radius, std::vector<Vector3f>& data, int accum=10) 
{ 
    assert(!(data.size() % 3)); 

    std::vector<Vector3f> newData; 

    for(int i=0; i<data.size(); i+=3){ 
     /* Tesselate each triangle into three new ones */ 
     Vector3f centerPoint = (data[i] + data[i+1] + data[i+2])/3.0f; 

     /* triangle 1*/ 
     newData.push_back(data[i+0]); 
     newData.push_back(data[i+1]); 
     newData.push_back(centerPoint); 
     /* triangle 2*/ 
     newData.push_back(data[i+1]); 
     newData.push_back(data[i+2]); 
     newData.push_back(centerPoint); 
     /* triangle 3*/ 
     newData.push_back(centerPoint); 
     newData.push_back(data[i+2]); 
     newData.push_back(data[i+0]); 
    } 
    data = newData; 
    if(!accum){ 
     /* We're done. Normalize the vertices, 
      multiply by the radius and return. */ 
     for(int i=0; i<data.size(); ++i){ 
      data[i].normalize(); 
      data[i] *= radius; 
     } 
    } else { 
     /* Decrease recursion counter and iterate again */ 
     GenerateSphere(radius, data, accum-1); 
    } 
    return; 
} 

該代碼將與由逆時針三角形的任何多面體工作,但八面體是最好的。

0

。不是,確切地說是統一,但計算速度非常快。

0

下面是一個簡單的方法來做到這一點。

  1. 隨機,從單位立方體樣品,[0,1]^3

  2. 試驗列入球體。如果採樣點不在包含在單位立方體中的直徑1的球體內,則拒絕並且轉到步驟1.

  3. 將點標準化到球體表面上,方法是將點從外部投影球體的中心。

這通常會在幾個樣本之後成功。如果你願意,你也可以拒絕接近球體中心的樣本,以減少舍入誤差並使分佈更接近統一。

0

上面的細分方法絕對是要走的路。如果你想要一個任意指定數量的頂點,那麼我推薦:

首先,將點隨機均勻地分佈在球體上。 我詳細地談論了在http://elenzil.com/progs/randompoints這樣做。 我相信我的方法至少和worlfram一樣。

秒,通過將點視爲粒子系統來「放鬆」分佈,其中每個粒子排斥其他粒子。這裏的困難在於確保系統不會變得不穩定,並決定何時停止。我在這裏有一個這樣的例子:http://elenzil.com/progs/separate不幸的是,這些是我的項目包括源代碼之前的日子,所以代碼丟失了。

0

我試過一次下面的算法:

  • 開始與在球體上提交一個正四面體。
  • 挑選具有最大表面的三角形之一(最初將是四條邊中的任意一條)
  • 用三面金字塔替換所選面,其中第四點是面中心到球面的高程。
  • 重複,直到創建足夠的點數。

只要精度不會破壞均勻性,此工作正常。 生成的點形成類似於geode的數字。

您不需要計算任何曲面,因爲每個新三角不會比以前的所有曲面都大。只需按照FIFO順序處理它們。