Bentley-Ottmann算法用于寻找直线组的交点。但我有很多折线:
有没有办法找到折线组的交点?
我正在搞清楚,但与此同时,如果有人可以给出一些指示或想法,那将会有所帮助。谢谢阅读。顺便说一下,我正在使用WPF / C#,所有折线都是PathGeometry。
图片来源:http://www.sitepen.com/blog/wp-content/uploads/2007/07/gfx-curve-1.png
答案 0 :(得分:3)
扫描线算法有一个很好的理论,但很难强有力地实现。您需要处理垂直线段,并且可能存在两个以上线段在单个点相交(或甚至共享公共线段)的情况。
我使用R-Tree来存储折线的线段的边界框,然后使用R-Tree来查找可能相交的元素。只有这些需要进行交叉测试。优点是您可以为每条折线使用单独的R-Tree,从而避免在需要时检测自我交叉。
考虑使用CGAL的精确谓词内核来获得可靠的结果。
答案 1 :(得分:1)
添加Geom的建议(R-Tree是可行的方法),通过执行以下操作可以进一步提高性能:
1。简化折线 - 在保持折线的一般形状的同时,可以减少折线中的点数。这可以使用角度阈值并处理每个点或使用the Ramer-Douglas-Peucker algorithm来完成。根据您正在做的事情,您可能需要跟踪原始折线中的哪些点被用作简化折线的每个段的起点/终点(原始折线的点的索引)将需要存储在某处。)
在this example中,您可以看到折线的点数可以减少多少。红点表示原始折线未使用的点,绿点表示为构建简化折线而保留的点。
2. 将简化折线存储在R树中,并确定每条折线的每个线段之间的交点(比较线段的边界以减少计算有利于提高性能)。当这样做时,来自原始折线段的旧索引被存储为与每个检测到的交叉点有关的信息,以及相交的多段线(可以使用某种标识符)。这实际上为您提供了原始折线中每个线段的起点和终点,其中交叉点与其他折线存在。
3. 仅当交叉点位置必须与原始折线的交叉点的确切位置匹配时,才执行此步骤。您将需要返回并使用原始的非简化折线以及步骤2中获得的交叉点信息中的数据。每个交叉点应具有与之关联的开始和结束索引,并且这些索引可用于确定哪个需要处理原始折线的特定段。这将允许您仅处理必要的段(由交叉点信息存储的开始和结束索引给出)。另一种方法是使用点本身并向外扩展一个边界框,然后处理与该边界框相交的原始多边形线段(尽管这可能需要更长时间)。
4. 可能需要采取额外的步骤来检查每条折线的端点与其他所有折线的线段,因为简化过程可能会破坏某些端点交叉点。 (这通常很快)。
使用the Bentley-Ottmann algorithm(这是Geom所指的扫描线算法)可以进一步改进该算法。另请注意,根据所使用的简化算法和用于此类算法的参数(例如角度公差),可能需要在性能和准确度之间进行权衡(根据折线的简单程度,某些交叉点结果可能会丢失)。
显然,有些图书馆可能是可行的,但如果您因为您工作的公司或您正在处理的产品而受到许可条款的限制,第三方图书馆可能不会一个选项。此外,其他库可能无法满足要求。