两组线段的Bentley-Ottmann算法

时间:2010-12-29 11:38:12

标签: algorithm geometry computational-geometry line-intersection

Bentley-Ottmann算法用于计算线段的交点。

然而,我想找到两组线之间的交叉点,而不是找到它们之间所有线的交叉点。这就是说,对于行组A中的每一行,我想知道这些行与组B中的行之间的交叉点。

无论如何我可以延长Bentley-Ottmann algorithm吗?我已经实现了现有的Bentley-Ottmann算法(in the library of CGAL),我并不热衷于修改它。但是,我很想找到重用它并扩展它的方法。

编辑:欢迎任何其他算法(不一定基于Bentley-Ottmann)。如果这些算法已在现有库中实现,那就更好了。

4 个答案:

答案 0 :(得分:3)

您可以找到A+B中所有行之间的所有交叉点,然后删除同一组中行之间的交叉点。你没有增加太多的复杂性,这使得你只需要一个简单的包装函数即可使用CGAL的库函数。

答案 1 :(得分:0)

Bentley-Ottman保留按当前垂直位置排序的线段树,你不能保留两个树,A组和B组各一个吗?然后原始算法检查当前点上方和下方的邻居,您将检查上面的A邻居与下面的B邻居,反之亦然。

这是基于维基百科文章的快速浏览;在过去的十年里,我没有写过太多的几何代码。

答案 2 :(得分:0)

添加此答案的完整性,即使它可能不是2维的最有效方法。

在3D图形中,它与2个KD树相同,可用于检测所有重叠节点(可用于几何体上的布尔运算)。

工作示例(C代码)。 https://developer.blender.org/diffusion/B/browse/master/source/blender/blenlib/intern/BLI_kdopbvh.c;3b4a8f1cfa7339f3db9ddd4a7974b8cc30d7ff0b $ 1089

如果有许多小段(例如手绘线的路径),这将是相当有效的。但是,如果有许多长边(想想拾取棒) ......这将表现不佳,并且您希望在BVH树中拆分叶节点以获得更好的性能。但是,如果是这样的话,最好使用其他答案中建议的其他方法。

答案 3 :(得分:0)

是的Bentley-Ottmann算法可以与其他方法一起扩展。

在文献中,您描述的任务是报告红线和蓝线之间的交叉点

这是一篇将B-O扫描扩展到最优算法的论文。 http://www.cs.unc.edu/~snoeyink/demos/rbseg/jcdcg25.pdf

我不同意@ marcog关于复杂性的说法。论文链接声称O(n log(n + k))的最佳时间,如果过滤交叉点,则必须对所有行执行BO扫描,并且它将是((n + k)log n)。

还有其他类似的算法可能不需要复杂的数据结构http://www.cs.swarthmore.edu/~adanner/cs97/s08/pdf/palazzi93counting.pdf

对于边缘之间的较少边和较少的交叉点,@ marcog的回答中的解决方案可能运行良好。 (以下是CGAL http://doc.cgal.org/latest/Arrangement_on_surface_2/Arrangement_on_surface_2_2consolidated_curve_data_8cpp-example.html)的示例。

如果您需要处理复杂的多边形(GIS数据等)或需要通用算法,这类算法可能值得。