如何让程序从坐标数组中识别正方形?
How to get a program to identify a square from an array of coordinates?
我正在尝试创建一个程序,用户可以在其中单击网格上的正方形内部并使用 PyQt5 (QPainter) 创建正方形,但我无法让程序识别何时何地绘制线条。所有点击的点都存储在一个列表中。
clicked0 = [] #clicked points
distlist0 = [] # list of distances between 2 points
distdict0 {} = # dictionary to identify which two points go with each distance
#there are versions of these for both player 0 and player 1
这是我用来尝试让程序识别和绘制正方形的代码:
for i in list(itertools.combinations(clicked0, 2)):
woo = list(chain.from_iterable(i))
dist = math.hypot(woo[2]-woo[0],woo[3]-woo[1])
distlist0.append(dist)
distdict0[str(dist)] = "("+str(woo[0])+","+str(woo[1])+"), ("+str(woo[2])+","+str(woo[3])+")"
listy = list(itertools.combinations(distlist0, 4))
for i in listy:
if i[0] == i[1] and i[0] == i[2] and i[0] == i[3]:
for item in i:
diction = list(chain.from_iterable(distdict0.get(str(item))))
diction = [int(diction[1]),int(diction[3]),int(diction[8]),int(diction[10])]
x,y = self.cell2coord(diction[0],diction[1]) #method to turn grid coords into x,y coords
x2,y2 = self.cell2coord(diction[2],diction[3])
qp.setPen(QPen(QColor(40, 85, 66), 5))
qp.drawLine(x, y, x2, y2)
这会导致 Python 最终变慢并崩溃,但这是视觉结果:
当可以从中创建正方形时,这些线应该连接彩色网格空间(角)。我已经在这部分代码上工作了几个小时,我只是不确定我能对 simplify/correct 这个过程做些什么。
一种方法是遍历所有坐标并检查它们是否形成正方形,例如:
请注意:此功能仅适用于与原始轴正交的矩形,对于倾斜的矩形,请参见下文
def rectangle(a, b, c, d):
#sort points so they can easily be compared
points = sorted([a, b, c, d])
#check if corners line up
if points[0][0] == points[1][0] and\
points[0][1] == points[2][1] and\
points[2][0] == points[3][0] and\
points[1][1] == points[3][1]:
return True
return False
#example data
lst_points = [[1,1],
[1,2],
[2,2],
[2,1],
[3,2],
[4,5],
[6,7],
[4,2],
[2,5]]
#loop over all sets of 4 points
for i in range(len(lst_points)):
for j in range(i+1, len(lst_points)):
for k in range(j+1, len(lst_points)):
for l in range(k+1, len(lst_points)):
#check if rectangle
if rectangle(lst_points[i],
lst_points[j],
lst_points[k],
lst_points[l]):
print lst_points[i], lst_points[j], lst_points[k], lst_points[l]
这输出
[1, 1] [1, 2] [2, 2] [2, 1]
[2, 2] [4, 5] [4, 2] [2, 5]
示例列表中仅有的两个方块
用这个数据画线应该比较容易。
此函数还检查某个角度下的矩形。
import numpy as np
def rectangleII(a,b,c,d):
points = sorted([a,b,c,d])
V1 = np.array(points[1]) - np.array(points[0])
V2 = np.array(points[2]) - np.array(points[0])
V3 = np.array(points[3]) - np.array(points[2])
V4 = np.array(points[3]) - np.array(points[1])
if np.all(V1 == V3) and np.all(V2 == V4):
if np.dot(V1, V2) == 0:
return True
return False
从列表中的所有点开始,取出第一个点并将其从列表中删除。由此,迭代地选择列表中的每个下一个点,并将其作为从第一个点开始的线段的端点。对于每个段,将有两个其他方块来检查该段是否是可能的方块的一部分。如果是,则继续检查其他两个角(其两个可能的位置现在已固定。)在任何一种情况下,继续下一个点以创建要测试的线段,直到测试了从第一个弹出点开始的所有线段。
重复上述操作(弹出下一个点并检查其所有段)直到列表少于 4 个点。
这是 O(N^2)。要检查正方形是否已填充,您可以使用正方形数组,但如果您使用键为 (x,y) 坐标(内容可以是颜色)的字典,则解决方案可以更好地扩展到更大的网格。
使用组合会产生更多的案例。 100分,就是3921225种组合。用上面的算法,就是n(n-1)/2 = 4950.
我怀疑我正在解决某人的家庭作业问题,但为了学习的兴趣,这里是找到一组正方形的代码,其中一个正方形是一组四个点。
#/usr/bin/python3
points = [ (0, 0), (0, 2), (0, 4), (2, 0), (2, 2), (2, 6), (4, 4) ]
grid = {}
for point in points:
grid[point] = 1
squares = set() # set of frozenset(p1, p2, p3, p4), each defining a square
while len(points) >= 4:
p1 = points.pop()
for p2 in points:
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
for delta in [(dy, -dx), (-dy, dx)]:
p3 = (p2[0] + delta[0], p2[1] + delta[1])
if grid.get(p3, False):
p4 = (p3[0] - dx, p3[1] - dy)
if grid.get(p4, False):
square = frozenset((p1, p2, p3, p4)) # frozen so it can be a set element
squares.add(square) # might be duplicate but that's OK
break
for square in squares:
print(list(square))
输出:
[(0, 4), (4, 4), (2, 6), (2, 2)]
[(2, 0), (0, 0), (0, 2), (2, 2)]
我正在尝试创建一个程序,用户可以在其中单击网格上的正方形内部并使用 PyQt5 (QPainter) 创建正方形,但我无法让程序识别何时何地绘制线条。所有点击的点都存储在一个列表中。
clicked0 = [] #clicked points
distlist0 = [] # list of distances between 2 points
distdict0 {} = # dictionary to identify which two points go with each distance
#there are versions of these for both player 0 and player 1
这是我用来尝试让程序识别和绘制正方形的代码:
for i in list(itertools.combinations(clicked0, 2)):
woo = list(chain.from_iterable(i))
dist = math.hypot(woo[2]-woo[0],woo[3]-woo[1])
distlist0.append(dist)
distdict0[str(dist)] = "("+str(woo[0])+","+str(woo[1])+"), ("+str(woo[2])+","+str(woo[3])+")"
listy = list(itertools.combinations(distlist0, 4))
for i in listy:
if i[0] == i[1] and i[0] == i[2] and i[0] == i[3]:
for item in i:
diction = list(chain.from_iterable(distdict0.get(str(item))))
diction = [int(diction[1]),int(diction[3]),int(diction[8]),int(diction[10])]
x,y = self.cell2coord(diction[0],diction[1]) #method to turn grid coords into x,y coords
x2,y2 = self.cell2coord(diction[2],diction[3])
qp.setPen(QPen(QColor(40, 85, 66), 5))
qp.drawLine(x, y, x2, y2)
这会导致 Python 最终变慢并崩溃,但这是视觉结果:
当可以从中创建正方形时,这些线应该连接彩色网格空间(角)。我已经在这部分代码上工作了几个小时,我只是不确定我能对 simplify/correct 这个过程做些什么。
一种方法是遍历所有坐标并检查它们是否形成正方形,例如:
请注意:此功能仅适用于与原始轴正交的矩形,对于倾斜的矩形,请参见下文
def rectangle(a, b, c, d):
#sort points so they can easily be compared
points = sorted([a, b, c, d])
#check if corners line up
if points[0][0] == points[1][0] and\
points[0][1] == points[2][1] and\
points[2][0] == points[3][0] and\
points[1][1] == points[3][1]:
return True
return False
#example data
lst_points = [[1,1],
[1,2],
[2,2],
[2,1],
[3,2],
[4,5],
[6,7],
[4,2],
[2,5]]
#loop over all sets of 4 points
for i in range(len(lst_points)):
for j in range(i+1, len(lst_points)):
for k in range(j+1, len(lst_points)):
for l in range(k+1, len(lst_points)):
#check if rectangle
if rectangle(lst_points[i],
lst_points[j],
lst_points[k],
lst_points[l]):
print lst_points[i], lst_points[j], lst_points[k], lst_points[l]
这输出
[1, 1] [1, 2] [2, 2] [2, 1]
[2, 2] [4, 5] [4, 2] [2, 5]
示例列表中仅有的两个方块
用这个数据画线应该比较容易。
此函数还检查某个角度下的矩形。
import numpy as np
def rectangleII(a,b,c,d):
points = sorted([a,b,c,d])
V1 = np.array(points[1]) - np.array(points[0])
V2 = np.array(points[2]) - np.array(points[0])
V3 = np.array(points[3]) - np.array(points[2])
V4 = np.array(points[3]) - np.array(points[1])
if np.all(V1 == V3) and np.all(V2 == V4):
if np.dot(V1, V2) == 0:
return True
return False
从列表中的所有点开始,取出第一个点并将其从列表中删除。由此,迭代地选择列表中的每个下一个点,并将其作为从第一个点开始的线段的端点。对于每个段,将有两个其他方块来检查该段是否是可能的方块的一部分。如果是,则继续检查其他两个角(其两个可能的位置现在已固定。)在任何一种情况下,继续下一个点以创建要测试的线段,直到测试了从第一个弹出点开始的所有线段。
重复上述操作(弹出下一个点并检查其所有段)直到列表少于 4 个点。
这是 O(N^2)。要检查正方形是否已填充,您可以使用正方形数组,但如果您使用键为 (x,y) 坐标(内容可以是颜色)的字典,则解决方案可以更好地扩展到更大的网格。
使用组合会产生更多的案例。 100分,就是3921225种组合。用上面的算法,就是n(n-1)/2 = 4950.
我怀疑我正在解决某人的家庭作业问题,但为了学习的兴趣,这里是找到一组正方形的代码,其中一个正方形是一组四个点。
#/usr/bin/python3
points = [ (0, 0), (0, 2), (0, 4), (2, 0), (2, 2), (2, 6), (4, 4) ]
grid = {}
for point in points:
grid[point] = 1
squares = set() # set of frozenset(p1, p2, p3, p4), each defining a square
while len(points) >= 4:
p1 = points.pop()
for p2 in points:
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
for delta in [(dy, -dx), (-dy, dx)]:
p3 = (p2[0] + delta[0], p2[1] + delta[1])
if grid.get(p3, False):
p4 = (p3[0] - dx, p3[1] - dy)
if grid.get(p4, False):
square = frozenset((p1, p2, p3, p4)) # frozen so it can be a set element
squares.add(square) # might be duplicate but that's OK
break
for square in squares:
print(list(square))
输出:
[(0, 4), (4, 4), (2, 6), (2, 2)]
[(2, 0), (0, 0), (0, 2), (2, 2)]