合并相似项目的数据结构/算法

时间:2019-03-18 21:15:35

标签: algorithm data-structures language-agnostic computational-geometry

要求:

给定2D平面中的线段束,我需要能够合并彼此相似或相等的所有线段。

例如,如果给我两个线段(0, 0) - (1, 1)(1, 1) - (2, 2)。这两条线是连接的,并且具有相同的斜率。因此,我可以将这两部分合并成一行(0, 0) - (2, 2)

对于线段(0, 0) - (1, 1)(1.01, 1) - (2, 2)。尽管它们的斜率有些不同并且没有连接,但是人眼看不到它的斜率,因此我仍然将这两个合并到(0, 0) - (2, 2)中以换取性能。

对于线段(0, 0) - (1, 1)(0.5, 0.5) - (0.6, 0.6)。后者只是前者的一部分,因此可以安全地删除后者并仅保留前者。

很明显,我可以用野蛮的力量O(n^2)来做到这一点,但这花了太长时间。是否有一个好的算法/数据结构可以帮助减少运行时间?

尝试:
范围树:由于它支持范围查询(斜率相似的线),因此看起来很自然。但是不支持插入/删除。

R树:R树支持通过使用矩形来查询关闭的元素。使用此方法,我首先可以找到边界框中的所有线,并过滤出斜率差> epsilon或距离> epsilon2的线。但是我找不到关于实现的好的描述(搜索看起来有据可查,但插入/删除非常含糊)

B树:B树看起来很有前途,但似乎我的用例不是它的主要用法。不知道这是否是正确的方法。

3 个答案:

答案 0 :(得分:2)

您可以将projective duality与您喜欢的邻近结构(kd树,覆盖树等)一起使用,以将线段聚类为几乎共线的组。然后,对于每个组,您可以使用标准扫掠线算法将间隔的并集计算为不相交的间隔列表。

要计算包含(a, b)(c, d)的线的投影坐标,我们在投影空间中将端点嵌入为(a, b, 1)(c, d, 1),然后计算{{ 3}}。投影坐标的问题是它们不是唯一的。我幼稚的建议是通过相对于欧几里得范数进行标准化并复制其对映点来将3D单位球体用作覆盖空间。

换句话说,我们将(a, b) - (c, d)映射到(x', y', z')(-x', -y', -z'),其中(x, y, z) = (b - d, c - a, ad - bc)x' = x/sqrt(x^2+y^2+z^2)以及y' = y/sqrt(x^2+y^2+z^2)z' = z/sqrt(x^2+y^2+z^2)

答案 1 :(得分:1)

您尝试了Sweep line algorithm吗?您可以找到/计数/检测line segment intersections,这听起来确实像第一步(检测是否有交叉点,然后检查坡度)。您可以使用Bentley-Ottman algorithm解决O((n + k)logn)(其中k是交点数)的问题。基本上,您可以对线段进行排序,然后按该顺序用一条线在平面上滑动,然后在每个交叉处停止。

另一件事,您可以计算斜率,然后可以按字典顺序排序,首先按斜率,然后按x坐标(或投影到斜率穿过0点的线),然后遍历该段订购。然后,您可以执行简单的“扫行”,只需验证分段的距离并合并即可。您可以在坡度上添加一些误差,因此也可以将相似的坡度放在同一存储桶中。

答案 2 :(得分:0)

将线Ax + By + C = 0映射到(A,B,C)时的问题是,如果斜率略有不同的两条相似线段离原点很远,则C之间的差异变大,从而阻止了两者细分成一个整体。

另一方面,如果两个线段的斜率非常不同,则如果其中一个线段非常短,它们在视觉上仍然可以视为“相似”。

我怀疑是否有任何对偶映射->聚类->过滤方法可以完全解决这个问题。考虑以下两种极端情况:

  • 线段AB,A处的无限小线段,B处的无限小线段->等价性不成立->永远不能照原样对线段进行聚类->必须首先对线段进行聚类线,然后处理线段
  • 线AB和CD具有相似的斜率。如果线段A'B'和C'D'靠近交点,则它们“相似”;否则,它们不是->聚类后无法处理线段

产生矛盾。

在我看来,O(N ^ 2)可能是您可以获得的最好的,这是基于以下事实:对于每个线段,最坏的情况是在整个线包中(或其余的)中搜索)。尽管如此,假设线段是随机分布的,使用一些空间分割技术,您可以获得更好的平均大小复杂度。

相关问题