问题描述
我目前正在从事一个有趣的项目,寻找在 2D 点分布中查找重复组。每组由四个点组成,它们的相对位置受到一些边界条件的约束。我正在尝试寻找自动群组查找器和群组匹配器。
点数据由二维数组组成。我们有N点。
points = array[N,2]
每组(“工具”)由四个点(a、b、c、d)组成,这些点位于正方形(长度=L)的边缘,但其位置可以是少量改变(位移=D)。这里的值是 L=1.000,D=0.150。
目前我的方法如下:
- 加载所有的点数据(points)
- 迭代每个点p 点
- 搜索a,b,c,d四个象限内的所有点(相对于点p)
- 对于所有找到的点 (a,d) 的每个组合 q
- 检查组合q是否可行(点之间的距离dist:L-D dist
- 在 toolList TL 中存储组合 q
在解析点数据后,我尝试找到最常用的工具。 toolList TL 是一个 8 维空间。但是因为每个步骤 4 都有很多组合,所以这个工具空间非常混乱。
您还有其他更好的方法吗?
示例数据点(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 以显示为角捕获的点。