我需要一种算法来将一系列段合并/连接到一系列折线

时间:2016-09-02 09:54:31

标签: algorithm geometry spatial polyline segment

我有一系列片段,它们的末端最多相互交叉。我想将这些段合并为折线。

是否有一种算法在O(N_segments)中执行此操作而不使用额外的存储空间(例如,无需为分段点构建树或其他空间数据结构并进行处理)?

我所拥有的细分数量很少,O(10)。因此,将它们放入动态数据结构(如散列表或映射(红黑树))可能比最后的O(N^2)循环更昂贵,除非我将该数据结构放在堆栈上并且避免任何内存分配(我使用的折线是使用small_vector实现的,只要点数足够小就可以避免分配。

目前我已经想出了这个:

polylines = []
// 1. Append each segment to a range of polylines, merging when possible:
for each segment in segments:
    for each polyline in polylines:
       merge_result = merge(segment, polyline)
       if (not merge_result) continue
       polyline = merge_result
       goto done

    // either polylines empty or no merge possible
    polylines.append(segment)

    done:
      continue

// 2. Try to merge the polylines among themselves until no more merges are possible
// Pure brute force, quadratic
done = false
while not done:
    for p1 in polylines: 
        for p2 in polylines[p1..end]:
            merge_result = merge(p1, p2)
            if not merge: continue
            p1 = merge_result
            polylines.remove(p2)
            done = false
            goto restart
    restart: continue

但是第二个循环显然是二次的,所以我想知道是否有更好的算法来合并/连接/组合它们之间的一系列段。

2 个答案:

答案 0 :(得分:1)

我严重怀疑O(n)方法是否存在。

这是一个O(n log(n))方法,用于检测具有完全相同坐标的分段末端。它使用"数据结构",但它是一个非常简单的(只是一个向量):

1)创建所有段的所有末端的元素(x,y,i)的向量,其中x,y表示极值的坐标,i表示极值的索引(例如,2 *段索引)和2 *段索引+ 1段的两个末端)。

2)在(x,y)

上按字典顺序对矢量进行排序

3)扫描向量,具有完全相同坐标的点在向量中是连续的(对于索引i,您可以检索它们对应的段末端)

我正在使用此算法合并3D网格中的顶点,它简单而快速,比使用哈希映射或集合要快得多(在几秒内检测到点集中的重复点大到1000万点)。 / p>

答案 1 :(得分:0)

您的问题等同于在数组中查找重复项。在一般情况下,在O(N)时间和0(1)空间中不能解决该问题。您可以按照建议使用排序来使O(N log N)复杂,或使用数据结构。要查找常规案例中的重复项,您可以查看this讨论。对于特殊情况,当大小为n的数组包含范围0,... n-1中的元素时,有一个O(N)时间和0(1)空间解决方案,它使用可以将元素用作索引这一事实,请参阅this post。

然而,如果你只谈论大约10个元素,即使是二次循环也不会受到太大影响。如果时间真的至关重要,那么在任何情况下都应该对两种方法进行基准测试,而不是猜测。问题是,没有人可以告诉你哪一个在你的机器上只有10个元素会更快,因为纯复杂性类只对大N 变得重要。对于小N,O(N ^ 2)算法可以比O(N log n)算法快得多。此外,除了内存分配,缓存效率和其他任何其他功能。所以,我的建议是:如果你真的关心速度,要么是基准,要么如果你不关心,不要打扰。