在2D

时间:2018-01-06 12:53:03

标签: algorithm line geojson line-segment

point a  = [1,0]   
point b  = [3,0]
point c  = [3,3]
point b' = [3,0]

加入这些点将给出线路径 的 A-> B->℃下-b' b到c之间存在重叠并且返回到b`到c。 我想找到所有重叠的路径。

我试图解决的问题是识别这些重叠的线条并将它们绘制成曲线,以便用户区分它们。

案例1

a = [1,0]
b = [5, 0]
c = [3, 0]

存在重叠但用户可以清楚地看到重叠,所以我忽略了这种重叠。

案例2

a = [3,0]
b = [5, 0]
c = [1, 0]

如果我画直线a-b路径将被隐藏。所以在这种情况下绘制一条曲线。

enter image description here 我已经通过考虑每个N ^ 2组合线并比较它们的开始和结束lat long来实现代码。

line AB = [ [1,0], [3,0]]
line BC = [ [3,0], [3,3]]
(AB == BC || AB == flip(BC))

以下是代码链接

http://jsbin.com/qibarevodi/edit?js,console

http://bl.ocks.org/d/d21a0d3e6df2cd4bb08fbe2a6e66ceb8

是否有更有效的方法来找到重叠的线条。

2 个答案:

答案 0 :(得分:0)

这是我要做的。我将专注于简化你的问题,即我将每一行标记为"弯曲"如果它与任何其他重叠 - 重叠是坏的。我不会做出你所做的区分,因为它们是额外的,而不是简化。您的问题基本上采用以下形式:

在平面中给定一组线段,找到与其他线段重叠的线段

如果您仍想区分您所做的案件,您将不得不考虑订购它们并进行一些额外的检查。您可以使用额外的二进制坐标作为方向。

第一个问题是,我们如何存储线段?您似乎将它们视为指定为两个点(x1,y1)和(x2,y2),这就是您进行N ^ 2比较的原因。我建议你把它们作为起点和终点的线来威胁。这意味着,我们将使用它们的斜率m,y轴截距y以及x1,x2作为坐标。 找到y和m应该不难。 不幸的是,这对于y轴本身不起作用。如果您无法确定y轴上是否有分段,则可能需要修改此方法或考虑针对此特定情况的某种替代方法。也许给这些特殊的密钥并保留(y1,y2)值。

我现在的建议是将你的行存储在哈希表(可能类似于pythons字典)中,键(m,y)和列表内容[(x1,x2),(x1& #39;,X2'),...]。这允许您为每个段仅检查位于同一延长线上的段。 然后,您可以遍历所有行,并标记与另一个相同键重叠的行。别忘了使用fast overlap test这样做。

如果您想进一步提高效率,可能需要查看Interval trees。我自己并不太熟悉它们,但从理论上讲,您可以使用此数据结构或其中的一些修改来为列表中的间隔提供给定键以优化查找重叠的键。如果您在一个特定的行上有许多步骤,这将非常重要。只要与此树中的另一条重叠,就可以将一条线标记为弯曲。

您的算法可能类似于:

  • 将线段划分为斜率和y相交(即制作哈希表)
  • 循环使用哈希键
  • 对于列表中的每个元素,检查它是否与另一个元素重叠(这是Interval树可能会帮助您进一步加速的地方。它也是您的案例区分可能出现的地方)
  • 将线标记为"弯曲"如果支票是肯定的

解决一些评论:仅使用x轴的角度不会有帮助。此外,记住你来自的方向不会有所帮助,如下面的例子所示。

A graph

请注意,您测试的具体内容取决于您的预期结果。您可以测试重叠,或者您可以测试间隔是否完全包含在另一个中。 读取图形库及其可视化也可能是值得的,因为您的问题基本上描述了具有固定节点位置的有向图。 希望其中一些对您有所帮助。

答案 1 :(得分:0)

让我们从您的示例中假设您需要消除仅一条折线的视觉模糊:一组由线段连接的点。处理不止一个并不困难,但我不会讨论它。

你真的有两个不同的问题。

  1. 识别位于同一无限线上的多组线段。
  2. 对于带有线段的每条无限线,请标识需要表示为曲线的线,以消除点的遍历顺序。
  3. 第1部分很简单。以规范形式表示每个段所在的无限线。然后从规范形式构建一个映射到位于它们上的线段的列表(以折线顺序表示以后)。任意无限线的有用规范形式是单位方向向量d和最接近原点的唯一点p。这些计算简单快捷。对于点ab之间的细分,

    d = d' / length(d') where d' = [b.x - a.x, b.y - a.y]
    p = d_perp (d_perp dot a) where d_perp = [d.y, -d.x]
    

    处理点几乎在同一条线上但不完全相同的情况是一个很大的附加主题。如果您对解决方案感兴趣,我可以进一步研究。

    对于第2部分,我们可以将同一无限线L上的每组线段视为1-d问题。您似乎在说,在跟踪折线时,如果L上的任何线段覆盖已经跟踪的L上的顶点,则覆盖线段应为曲线。如果这个定义是准确的,它会直接导致简单的算法:

    for each line L
      let S be the subset of L already traced
      for each segment a->b lying in L (in polyline order taken from the map above)
        if a in S and b in S, then
          draw a->b with a curve
        else
          draw a->b with a straight segment
          add [a->b) to S
    

    表示法add [a->b) to S表示将线段从a添加到b,但不包括点b本身。这会考虑您的案例1

    上面的伪代码非常抽象。如何表示集S?也许最简单的是将点旋转到x轴上。这很简单,因为您已经拥有该行的规范形式。使用

    获取每个点p所需的x坐标
    x = d dot p
    

    现在,您可以将S存储为一组1d x坐标间隔的并集。这可以通过平衡二叉树非常容易地完成,其中键是不同的间隔。 (你不需要像间隔树这样复杂的东西,因为你要存储一个联合,而不是重叠的间隔。)

    如果您在制定细节时遇到问题,请与我们联系。这是一个很好的小问题。例如,有一些边缘案例需要思考。如果同一段在同一折线内重复怎么办?您没有提供有关问题的足够信息,以确定是否会发生这种情况。