如何检查笛卡尔坐标是否有效构成矩形?

时间:2011-05-18 11:19:03

标签: python algorithm optimization geometry coordinates

情况如下:

  • 有N个阵列。
  • 在每个数组(0..N-1)中存储了(x,y)元组(笛卡尔坐标)
  • 每个数组的长度可以不同

我想提取构成完整的坐标组合的子集 大小为N的转角。换句话说;所有笛卡尔坐标都是相邻的。

示例:

findRectangles({
    {*(1,1), (3,5), (6,9)}, 
    {(9,4), *(2,2), (5,5)}, 
    {(5,1)},
    {*(1,2), (3,6)}, 
    {*(2,1), (3,3)}
})

产生以下结果:

[(1,1),(1,2),(2,1),(2,2)],
..., 
...(other solutions)...

同一组中不能有两点。

我首先计算了笛卡尔积,但这很快就变得不可行了(我的用例目前有18个点阵列,每个阵列大致包含10个不同的坐标)。

2 个答案:

答案 0 :(得分:5)

您可以使用哈希效果很好:

hash each point (keeping track of which list it is in)
for each pair of points (a,b) and (c,d):
    if (a,d) exists in another list, and (c,b) exists in yet another list:
        yield rectangle(...)

当我说exists时,我的意思是做:

hashesToPoints = {}
for p in points:
    hashesToPoints.setdefault(hash(p),set()).add(p)
for p1 in points:
    for p2 in points:
        p3,p4 = mixCoordinates(p1,p2)
        if p3 in hashesToPoints[hash(p3)] and {{p3 doesn't share a bin with p1,p2}}:
            if p4 in hashesToPoints[hash(p4)] and {{p4 doesn't share a bin with p1,p2,p3}}:
                yield Rectangle(p1,p2)

这是O(#bins^2 * items_per_bin^2) ~30000,在您的18个数组和10个items_per_bin的情况下非常快速 - 比外部产品方法好得多......在O(items_per_bin^#bins) ~3万亿的情况下更糟糕。 =)


次要旁注:

您可以通过多次“修剪”来减少计算中的基数和指数。 e.g。

remove each point that is not corectilinear with another point in the X or Y direction
then maybe remove each point that is not corectilinear with 2 other points, in both X and Y direction

您可以根据X坐标进行排序,重复Y坐标,在O(P log(P))时间内按点数进行排序。您也可以在散列的同时执行此操作。如果一个坏人正在安排你的输入,他可以使这个优化根本不起作用。但根据您的分布情况,您可能会看到显着的加速。

答案 1 :(得分:0)

让XY成为你的数组。构造两个新的X和Y集合,其中X等于XY,所有数组都排序为x坐标,Y等于XY,所有数组都排序为y坐标。

  • 对于X中任何数组中的每个点(x0,y0):找到具有相同x坐标的每个点(x0,y1)和来自X的其余数组中的不同y坐标
  • 对于每对这样的点(如果存在):搜索Y以获得点(x1,y0)和(x1,y1)

设C为最大数组的大小。然后对所有集合进行排序需要时间O(N * C * log(C))。在步骤1中,找到单个匹配点需要时间O(N * log(C)),因为X中的所有数组都已排序。找到所有这些点是O(C * N),因为总共最多有C * N个点。由于Y被排序,步骤2需要时间O(N * log(C))。

因此,整体渐近运行时在O(C * N ^ 2 * log(C)^ 2)。

对于C == 10和N == 18,您将获得大约10.000次操作。乘以2,因为我因Big-O-notation而放弃了这个因素。

该解决方案的另一个好处是实现起来非常简单。您只需要数组,排序和二进制搜索,其中前两个很可能已经内置到语言中,二进制搜索非常简单。

另请注意,这是最差情况下的运行时,其中所有矩形都从相同的x坐标开始。在一般情况下,你可能会比这更好。