算法:在二维点分布中查找重复组

问题描述

我目前正在从事一个有趣的项目,寻找在 2D 点分布中查找重复组。每组由四个点组成,它们的相对位置受到一些边界条件的约束。我正在尝试寻找自动群组查找器和群组匹配器。

点数据由二维数组组成。我们有N点。

points = array[N,2]

每组(“工具”)由四个点(a、b、c、d)组成,这些点位于正方形(长度=L)的边缘,但其位置可以是少量改变(位移=D)。这里的值是 L=1.000,D=0.150。

Group matching pattern - Green: Base length L,Black: Movement radius

目前我的方法如下:

  1. 加载所有的点数据(points)
  2. 迭代每个点p
  3. 搜索a,b,c,d四个象限内的所有点(相对于点p
  4. 对于所有找到的点 (a,d) 的每个组合 q
  5. 检查组合q是否可行(点之间的距离dist:L-D dist
  6. 在 toolList TL
  7. 中存储组合 q

在解析点数据后,我尝试找到最常用的工具。 toolList TL一个 8 维空间。但是因为每个步骤 4 都有很多组合,所以这个工具空间非常混乱。

您还有其他更好的方法吗?

附加您可以找到一些示例数据:

Example data


示例数据点(2 个组合,每个组合 10 次重复)

points =[[0.016,0.920],[0.995,1.080],[0.041,-0.069],[0.957,0.039],[1.496,1.081],[2.582,0.932],[1.536,0.015],[2.541,0.095],[0.516,1.420],[1.495,1.580],[0.541,0.431],[1.457,0.539],[1.996,1.581],[3.082,1.432],[2.036,0.515],[3.041,0.595],[1.016,1.920],[1.995,2.080],[1.041,0.931],[1.957,1.039],[2.496,2.081],[3.582,1.932],[2.536,1.015],[3.541,1.095],[1.516,2.420],[2.495,2.580],[1.541,1.431],[2.457,1.539],[2.996,2.581],[4.082,2.432],[3.036,1.515],[4.041,1.595],[2.016,2.920],[2.995,3.080],[2.041,1.931],[2.957,2.039],[3.496,3.081],[4.582,2.932],[3.536,2.015],[4.541,2.095],[2.516,3.420],[3.495,3.580],2.431],[3.457,2.539],[3.996,3.581],[5.082,3.432],[4.036,2.515],[5.041,2.595],[3.016,3.920],[3.995,4.080],2.931],[3.957,3.039],[4.496,4.081],[5.582,3.932],[4.536,3.015],[5.541,3.095],[3.516,4.420],[4.495,4.580],3.431],[4.457,3.539],[4.996,4.581],[6.082,4.432],[5.036,3.515],[6.041,3.595],[4.016,4.920],[4.995,5.080],3.931],[4.957,4.039],[5.496,5.081],[6.582,4.932],[5.536,4.015],[6.541,4.095],[4.516,5.420],[5.495,5.580],4.431],[5.457,4.539],[5.996,5.581],[7.082,5.432],[6.036,4.515],[7.041,4.595]]

解决方法

假设 l >> d 我将点放在 d 大小的网格上并寻找 l // d 方格,然后转换回原始点。 请注意,多个点可以映射到同一个 d-grid 点,因此答案以表示正方形的列表形式给出。正方形是一个正方形的四个角点列表,其中任何角都可以由 d 邻域中的多个点表示。

import random
from collections import defaultdict


l = 205     # Square side
d = 25      # point +/- delta

# Up to max_points distinct integer points in range 0..r_max
r_max = 1_750
max_points = 1_000
points_x = random.sample(range(r_max),max_points)
points_y = random.sample(range(r_max),max_points)
points = list(set(zip(points_x,points_y)))


dgrid_2_points = defaultdict(list)  # Move points to d-sized grid
for x,y in points:
    dgrid_2_points[(x // d,y // d)].append((x,y))

d_l = l // d  # Square side in d-grids

d_points_set = set(dgrid_2_points)      # gridded points to check
d_points = sorted(d_points_set)         # order for checking

d_found = []            # Squares found on d-grid
for a in d_points:
    x,y = a
    b,c,d = (x,y+d_l),(x+d_l,y)
    if all(p in d_points_set for p in (b,d)):
        d_found.append((a,b,d))
    d_points_set.remove(a)


found = [[dgrid_2_points[d_pt] for d_pt in d_square]
         for d_square in d_found]

"""
# EXAMPLE VALUE

found = \
[[[(236,823),(240,819)],[(239,1018)],[(446,1005)],[(425,824)]],[[(540,282)],[(534,496)],[(726,491)],[(733,283)]],[[(586,172)],[(585,355)],[(794,363)],[(797,174)]],[[(755,67)],[(763,257)],[(972,252)],[(958,66)]],[[(924,197)],[(912,382)],[(1124,393),(1104,381)],[(1115,181)]],[[(1375,28)],[(1386,245)],[(1581,246)],[(1586,43)]]]

"""

该示例显示它找到了六个正方形。找到的第一个正方形将以下两个点之一作为一个角: [(236,819)] 它的其他三个角是单个点。

注意:我应该使用 d/2 网格而不是我确实使用的 d 网格可能会出现错误。你需要检查一下。在这种情况下,只需替换原始 d 值的一半,并假设您报告的是 d。

与您的示例要点

您现在已经给出了一组示例点。

  • 根据您的积分运行,l 为 1,d 为 0.15,我发现没有 方块。
  • d 乘以 2,然后我找到六个正方形,其中一些角被多个点占据。
# YOUR EXAMPLE

l = 1.0
d = 0.15
points = ...

found = [] # Nothing

# Change d

d = 0.15 * 2

found = [
 [[(0.995,1.08),(1.041,0.931)],[(1.016,1.92)],[(1.995,2.08),(2.041,1.931)],[(1.957,1.039)]].
 [[(2.582,0.932),(2.536,1.015)],[(2.496,2.081)],[(3.582,1.932),(3.536,2.015)],[(3.541,1.095)]].
 [[(2.495,2.58),(2.541,2.431)],[(2.516,3.42)],[(3.495,3.58),(3.541,3.431)],[(3.457,2.539)]].
 [[(4.082,2.432),(4.036,2.515)],[(3.996,3.581)],[(5.082,3.432),(5.036,3.515)],[(5.041,2.595)]].
 [[(3.995,4.08),(4.041,3.931)],[(4.016,4.92)],[(4.995,5.08)],[(4.957,4.039)]].
 [[(5.582,3.932),(5.536,4.015)],[(5.496,5.081)],[(6.582,4.932)],[(6.541,4.095)]].]

这是您所期望的吗?

图表

红色是找到的正方形,蓝色延伸 +/- 一半 d 以显示为角捕获的点。

Graph of example points and found squares