如何计算包围其他边界球的最小边界球

时间:2012-01-30 11:51:55

标签: math collision-detection

我正在寻找一个有人可以访问的算法,它将计算包含一组其他边界球体的最小边界球体。我已经考虑了一段时间并提出了一些初步的解决方案,但我不相信这些解决方案必须是最准确或最不昂贵的(最快的)。

第一个想法

我的第一个解决方案是最简单的天真解决方案,即平均球形中心以获得中心点,然后计算从计算中心到每个球体中心的最大距离加上其半径,作为半径。所以伪代码就像:

function containing_sphere_1(spheres)
  center = sum(spheres.center) / count(spheres)
  radius = max(distance(center, spheres.center) + radius)
  return Sphere(center, radius)
end

然而,我感觉它不是那么便宜,也不是很准确,因为得到的球体可能比它需要的大得多。

第二个想法

我的第二个想法是使用迭代算法来计算最小边界球。它是通过连续测试另一个球体来计算的,如果测试的球体在边界内,则不做任何事情,否则从可用的两个球体计算新的边界球体。新的边界球体的中心位于两个中心之间的矢量之间,如果它延伸到球体表面,半径是该线条长度的一半(从新中心到球体表面)。 / p>

function containing_sphere_2(spheres)
  bounds = first(spheres)
  for each sphere in spheres
    if bounds does not contain sphere
      line = vector(bounds.center, sphere.center)
      extend(line, bounds.radius)
      extend(line, sphere.radius)
      center = midpoint(line)
      radius = length(line) / 2
      bounds = Sphere(center, radius)
    end
  end
  return bounds
end

起初我以为这将是要走的路,因为它是迭代的,似乎相当逻辑上一致,但是通过莫·韦尔泽我做一些阅读,最引人注目的文章“最小包围盘(球和椭球)”后”我不太确定。

Welzl的算法

据我所知,该算法的基础是3维中一组点上的最小边界球可以由最多4个点(在封闭球体的表面上)确定。因此,该算法通过选择4个点进行迭代,然后测试其他点以查看它们是否在内部,如果它们不是新的边界球,则构造特征为新点。

现在算法严格处理点,但我认为它可以应用于处理球体,主要复杂因素在构造封闭球体时会对半径产生影响。

回到问题

那么什么是'最佳',至少是计算成本最高的算法,为一组给定的球体创建一个最小的边界球?

我在这里描述了其中一个答案吗?一些伪代码或算法会很棒。

2 个答案:

答案 0 :(得分:10)

从封闭点到封闭球体的步骤非常重要,正如K. Fischer的论文中的discussion of Welzl's algorithm (which works to enclose points)所解释的那样,“最小的球包围”。见第二节。 5.1。

第4章介绍了“封闭点”材料,然后第5章介绍了“封闭球体”。

如果你只是在寻找一个实现,那么自从3.0版以来,Fisher论文中描述的算法就已经实现了in the CGAL package

答案 1 :(得分:0)

这是一种基于Ritter算法的快速近似最优方法  https://en.wikipedia.org/wiki/Bounding_sphere

对于每个球体,找到其最小/最大x / y / z点。将这6个点扔进水桶。当你完成所有N个球体时,你将拥有6N点的一桶。使用任何已知算法为这些找到边界球。

无论算法如何,你获得的边界球很可能会有点太小。然后你可以进行Ritter方法的第二次传递,但是使用球体的背面作为要测试的点。 '背面'意味着球体离目前的球体中心最远的球体。如果球体的背面pt在当前的bnd球体之外,则生长bnd球体以包含它。

除了6个极值之外,您最初可以包含刻录立方体的8个角:

([+/-] kR,[+/-] kR,[+/-] kR),其中k = sqrt(3)/ 3。这给出了14个分布相当均匀的地理位置。