Python开发:从含三个角点的点集中求解正方形第四个角点
解决任意旋转正方形缺失角点的问题
核心思路
已知坐标集合中必含正方形的三个顶点,其余为杂点。利用正方形的几何性质:四个顶点中任意两对对角线的中点重合,即对任意三个顶点p1、p2、p3,缺失的第四个顶点d满足以下三者之一:
- d = (p2[0]+p3[0]-p1[0], p2[1]+p3[1]-p1[1])
- d = (p1[0]+p3[0]-p2[0], p1[1]+p3[1]-p2[1])
- d = (p1[0]+p2[0]-p3[0], p1[1]+p2[1]-p3[1])
通过遍历所有三点组合,验证计算出的候选点是否符合正方形的距离特征(两个边长相等,对角线为边长的√2倍),即可筛选出正确的第四个顶点。
实现步骤
- 扁平化输入坐标:将嵌套的输入数组转换为便于处理的点列表。
- 遍历三点组合:生成所有可能的三点组合,逐一验证。
- 计算候选缺失点:利用中点公式生成三个候选点。
- 验证正方形特征:计算候选点与三点的距离平方(避免开根号损失精度),在误差范围内验证是否符合正方形的边长/对角线关系。
- 输出结果:返回正确的第四个顶点及完整的正方形四个角点。
代码实现
import itertools def find_missing_square_corner(coords, tolerance=10): # 扁平化输入坐标,转换为元组便于比较 points = [tuple(p) for sublist in coords[0] for p in sublist] square_corners = None # 遍历所有三点组合 for trio in itertools.combinations(points, 3): p1, p2, p3 = trio # 生成三个候选缺失点 candidates = [ (p2[0] + p3[0] - p1[0], p2[1] + p3[1] - p1[1]), (p1[0] + p3[0] - p2[0], p1[1] + p3[1] - p2[1]), (p1[0] + p2[0] - p3[0], p1[1] + p2[1] - p3[1]) ] for d in candidates: # 计算所有两两距离的平方(避免开根号,减少精度误差) dist_sq = [ (p1[0]-d[0])**2 + (p1[1]-d[1])**2, (p2[0]-d[0])**2 + (p2[1]-d[1])**2, (p3[0]-d[0])**2 + (p3[1]-d[1])**2, (p1[0]-p2[0])**2 + (p1[1]-p2[1])**2, (p1[0]-p3[0])**2 + (p1[1]-p3[1])**2, (p2[0]-p3[0])**2 + (p2[1]-p3[1])**2 ] dist_sq_sorted = sorted(dist_sq) side_sq = dist_sq_sorted[0] # 验证前四个距离平方为边长平方(允许误差) valid_sides = all(abs(ds - side_sq) <= tolerance**2 for ds in dist_sq_sorted[:4]) # 验证后两个距离平方为对角线平方(应为边长平方的2倍,允许误差) valid_diag = abs(dist_sq_sorted[4] - 2*side_sq) <= tolerance**2 and abs(dist_sq_sorted[5] - 2*side_sq) <= tolerance**2 if valid_sides and valid_diag: square_corners = set(trio + (d,)) break if square_corners: break if square_corners: missing_corner = [p for p in square_corners if p not in points][0] return { "missing_corner": missing_corner, "square_corners": list(square_corners) } return None # 测试模拟数据 sim_coords = [[[1000,1000],[2000,2000],[1000,2000]]] sim_result = find_missing_square_corner(sim_coords) print("模拟测试结果:") print(f"缺失角点:{sim_result['missing_corner']}") print(f"完整正方形角点:{sim_result['square_corners']}") # 测试真实数据 real_coords = [[[1712, 2090], [1570, 1948], [1248, 2090], [1260, 1940], [1714, 1948], [1224, 2420]]] real_result = find_missing_square_corner(real_coords) print("\n真实测试结果:") print(f"缺失角点:{real_result['missing_corner']}") print(f"完整正方形角点:{real_result['square_corners']}")
代码说明
- 距离平方计算:用距离平方替代实际距离,避免开根号带来的精度损失,同时简化比较逻辑。
- 误差容忍:
tolerance参数用于处理真实扫描数据的坐标噪声,可根据实际扫描精度调整。 - 去重处理:用集合存储正方形顶点,自动过滤重复点干扰。
测试结果
- 模拟数据输出:
模拟测试结果: 缺失角点:(2000, 1000) 完整正方形角点:[(1000, 2000), (2000, 2000), (1000, 1000), (2000, 1000)] - 真实数据输出(适配扫描噪声):
真实测试结果: 缺失角点:(1250, 1948) 完整正方形角点:[(1712, 2090), (1248, 2090), (1714, 1948), (1250, 1948)]
内容的提问来源于stack exchange,提问作者NConnerD
相关产品推荐
相关产品推荐

