假设有 n 三维物体(多面体)。是计算所有对象O(n ^ 2)?
的交集的最快方法现在,我正在使用一个基本上强制T(n)等于n ^ 2的库:
for each object: // there are n objects
get list of intersecting objects // this takes n steps
字面上需要n ^ 2步。
我能想到的唯一更快的方式仍然是O(n ^ 2),但是T(n)= n(n + 1)/ 2,或者(n * n + n) )/ 2。
这是伪代码:
for(int i = 0; i < len(objects) - 1; i++)
for(int j = i + 1; j < len(objects); j++)
if object at i intersects object at j:
object at i . addToIntersectList ( object at j )
object at j . addToIntersectList ( object at i )
这样我们就不必检查两个物体是否相交两次。我知道我正在迭代的列表中有大约3000个对象。该算法需要4501500步,而原始算法需要几乎两倍,9000000步。
我错过了什么吗?这是我们能得到的最好的吗?
答案 0 :(得分:3)
虽然有几种方法可以通过更改循环内容来提高O(n²)性能,但通过更改有关冲突检查方式的其他内容,可以做出重大改进。
代码中一个主要的低效率是它依赖于完全检查每个多面体与其他所有多面体的方式,这通常并不总是必要的。如果两个形状甚至不在一起,则不需要进行密集的交叉测试,如果有两个形状的簇由大片空间隔开,则不需要检查两个簇的每个成员另一个集群的每个成员。用于执行此类优化的一些技术包括:
您可以使用这些技术来主要加速碰撞搜索。
答案 1 :(得分:2)
信不信由你,我已经有效地在StackOVerflow上回答了这个问题,在这里:https://stackoverflow.com/a/19172550/109122。问题和答案是多边形(2D),但它应该同样适用于多面体(3D)。
那里的问题还提到了被认为是最快的算法,Hoey Shamos扫描线技术,即O(n Log n)。你可以研究和实现它,但它很复杂。
我在答案中演示的更简单的算法具有高度依赖于形状及其定位“表现良好”的性能。形状越狂野,它们的包装/重叠就越密集,它的表现就越差。然而,在表现良好的形状(即凸起或大部分如此)中,交叉点很少且包装不太密集,我发现它的性能优于O(n sqrt(n))。这里的代码和讨论主要是关于两个多边形内的线条,但这也推广到多边形本身。
除了相对简单之外,我的方法的一大优势在于,它可以独立于您用于检测两个多边形之间重叠的任何函数而应用。它只是用一系列更复杂的预测试替换你的双嵌套循环。
答案 2 :(得分:0)
您可以将所有对象放在3D树结构中。然后你只需要检查那些“关闭”的对。在某种意义上相互对立。
这是存储空间信息的典型方式。例如。 neo4j spatial在引擎盖下有一个k树,用于存储位置并“靠近”。类型查询。