【问题标题】:Is there an efficient way to count the number of intersections among a given set of line segments?有没有一种有效的方法来计算一组给定线段之间的交叉点数?
【发布时间】:2012-12-23 06:06:14
【问题描述】:

假设我在一般位置有 n 条线段。对于我的 n 个片段中的每一个片段,我如何快速计算它与其他 n-1 个片段相交的数量?

我可以在 O(n2) 时间内天真地做到这一点。我可以在 O((n + k) log n) 时间内使用相当简单的扫描线算法(Bentley-Ottmann)找到所有交叉点,其中 k 是此类交叉点的数量,然后将我找到的交叉点聚合成一堆很重要。

不过,我不需要找到交叉点;我只想知道有多少。我看不出如何将扫描线算法修改得更快,因为它需要为每个交叉点在树中重新排序两个东西,而且我想不出任何其他不会遇到同样问题的技术。

我也有兴趣了解如何计算总共有多少个交叉口。

【问题讨论】:

    标签: algorithm language-agnostic geometry computational-geometry


    【解决方案1】:

    在一般情况下,我很难相信您可以比 Bentley Ottman 做得更好。如果您不在乎线段相交的位置,您可以稍微简化计算,但我不明白如何在不找到交叉点的情况下计算交叉点。

    本质上,Bentley Ottman 是一种简化交叉路口搜索空间的方法。还有其他方法可能适用于线段的特定排列,但除非您的线段之间存在一些可预测的几何关系,否则您将无法比首先使用一些巧妙的方法找到候选交叉点并结合对每个候选人进行单独验证。

    除非您的问题域具有一些可能提供可利用子结构的特定功能,否则我认为您最好的速度选择是采用 Bentley Ottman(或一些类似的扫描算法)进行并行执行。 (将线段剪成条带很简单。找出一组最佳的条带也很有趣。)当然,这是一种实践而非学术练习;并行算法很可能最终会做更多的工作;它只是利用硬件在(恒定因素)更少的时间内完成工作。

    【讨论】:

    • 我有...不太难相信扫线方法可以被打败。考虑一下我可以计算 n 条线段之间的交点数量,这些线段的左端点都具有 x 坐标 0,右端点都具有 x 坐标 1;这只是计算数组中反转的经典问题。所以,至少在某些特殊情况下,我应该能够找到这种子结构并以某种方式利用它。
    • @tmyklebu,当然,如果有一个可利用的子结构,你可以很容易地利用它。但你必须先了解它。您可以在O(n) 中轻松检查单位方形情况,但除非您有充分的理由相信这很可能,否则这将是愚蠢的。 (对于其他特殊情况也是如此,例如凸多边形的集合。)这种情况不是“一般情况”。 B-O 将很好地处理多边形集合的情况,因为它加快了实际交叉点的减少。
    • B-O 可以很好地处理只有少数交叉点存在的情况。当我有一堆多边形时,我仍然可以提出粗略的情况(想象一大堆以同一点为中心但以随机角度旋转的等边三角形)。可利用的子结构是……问题的重点。 :) Chazelle 的一篇论文(“报告和计算段交叉点”)似乎使用了这种垂直分解的想法,并声称有一个 O(n1.695) 时间算法来解决我的问题,但似乎依赖于一个非常不切实际的数据结构。总比没有好。
    • n^2 和 n^1.695 的差值约为 10^6 的 70:1。因此,要使这样的算法实用(假设有一百万条线段在正常问题域中),它必须在其内部循环中完成不少于 70 倍的工作。据我了解该解决方案所基于的 Welzl 的工作,主要成本将是共轭树的构建,但也许我错了。查找比通过四叉树运行更多的工作,但它只是一点代数。我认为这都是一个有趣的学术活动。玩得开心....
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多