2010-12-03 128 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顺序处理它们。