【问题标题】:Algorithm to find intersections between polylines寻找折线之间交点的算法
【发布时间】:2011-11-14 09:18:05
【问题描述】:

Bentley-Ottmann 算法适用于寻找一组直线的交点。但是我有很多折线:

有没有办法找到这组多段线的交点?

我正在弄清楚,但与此同时,如果有人可以提供一些指示或想法,那将很有帮助。谢谢阅读。顺便说一句,我使用的是 WPF/C#,所有的折线都是 PathGeometry。

图片来源:http://www.sitepen.com/blog/wp-content/uploads/2007/07/gfx-curve-1.png

【问题讨论】:

  • 您仍然可以使用 Bentley-Ottmann。
  • 谢谢巴特。你能解释一下吗?它不会找到连接折线本身的交点吗?
  • 是的,每当您找到交叉点时,您都​​会检查它是否是两条线段的“真实”交叉点,或者属于同一折线的两条相连线段的点。
  • 添加了一些元数据并做到了。但是有没有专门针对折线的算法?
  • @Sam 你在math.stackexchange.com上问这个问题可能会更好

标签: wpf algorithm computational-geometry polyline line-intersection


【解决方案1】:

扫描线算法有一个很好的理论,但很难稳健地实现。您需要处理垂直线段,并且可能存在两条以上的线段在一个点相交(甚至共享一条公共线段)的情况。

我会使用 R-Tree 来存储折线的线段的边界框,然后使用 R-Tree 来查找可能相交的元素。只有这些需要进行交叉测试。优点是您可以为每条折线使用单独的 R-Tree,从而避免检测到自相交(如果需要)。

考虑使用 CGAL 的精确谓词内核来获得可靠的结果。

【讨论】:

    【解决方案2】:

    添加到 Geom 的建议(R-Tree 是要走的路),通过执​​行以下操作可以获得进一步的性能改进:

    1. 简化折线 - 可以减少折线中的点数,同时保持折线的一般形状。这可以使用角度阈值并处理每个点或使用the Ramer-Douglas-Peucker algorithm 来完成。根据您在做什么,您可能需要跟踪原始折线中的哪些点被用作简化折线的每一段的起点/终点(原始折线点的索引需要存储在某处)。

    this example 中,您可以看到如何减少折线的点数。红点表示原始折线中未使用的点,绿点表示为构建简化折线而保留的点。

    2.将简化的折线存储在R-Tree中,并确定每条折线的每个线段之间的交点(比较线段的边界以减少计算有利于性能)。在此过程中,来自原始折线段的旧索引被存储为与每个检测到的交叉点相关的信息,以及与哪些折线相交的信息(可以使用某种标识符)。这实质上为您提供了原始折线中每个线段的起点和终点边界,其中交点彼此存在折线。

    3. 仅当交点位置必须与原始多段线交点的确切位置匹配时才执行此步骤。您将需要返回并使用原始的非简化折线,以及在步骤 2 中获得的交叉点信息中的数据。每个交叉点应该有一个与之关联的开始和结束索引,这些索引可用于确定哪些需要处理原始折线的特定段。这将允许您仅处理必要的段(由与交叉点信息一起存储的开始和结束索引给出)。另一种方法是使用点本身并向外扩展边界框,然后处理与该边界框相交的原始多段线段(尽管这可能需要更长的时间)。

    4. 可能需要采取额外的步骤来检查每条折线的端点与其他每条折线的线段,因为简化过程可能会剔除一些端点交叉点。 (这通常很快)。

    该算法可以通过使用the Bentley-Ottmann algorithm 进一步改进(这是Geom 所指的扫描线算法)。另请注意,根据使用的简化算法和此类算法使用的参数(例如角度公差),可能需要在性能和准确性之间进行权衡(根据折线的简单程度,可能会丢失一些相交结果)。

    显然,有些库可能是可行的,但如果您因工作的公司或所从事的产品而受到许可条款的限制,则可能无法选择第三方库。此外,其他库的性能可能不如要求的那么好。

    【讨论】:

      猜你喜欢
      • 2015-02-28
      • 2011-11-29
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      相关资源
      最近更新 更多