我正在尝试在python(2.7)中编写一个函数。
此函数将获取8个值的列表,这些值表示顶点的坐标
(输入的形式是[Ax,Ay,Bx,By,Cx,Cy,Dx,Dy])
该函数将确定是否给出这些顶点以形成有效的矩形。
如果没有,它将按顺序放置它们并返回这些顶点的排序列表。 起点或方向(无论是顺时针还是逆时针)并不重要。
让我模仿我想要的东西:
如果给定的输入在下面的链接中形成第二或第三形状;该函数将其转换为第一个。
http://i.stack.imgur.com/IsRqr.png
我使用了Alexey建议的方式并编写了我的代码。 它可能需要一些优化,但对我来说这不是必要的。
def crossProduct(vector1,vector2) :
a,b,c = vector1
d,e,f = vector2
vector3 = (b*f-c*e , -a*f+c*d , a*e-b*d)
return vector3
def fixRect(rectList) :
Ax,Ay,Bx,By,Cx,Cy,Dx,Dy = rectList[:]
v12 = (Bx-Ax,By-Ay,0)
v13 = (Cx-Ax,Cy-Ay,0)
v14 = (Dx-Ax,Dy-Ay,0)
z1 = crossProduct(v13,v12)[2]
z2 = crossProduct(v13,v14)[2]
if z1*z2 < 0 : # if two z values have different sign, they are in order
return [Ax,Ay,Bx,By,Cx,Cy,Dx,Dy]
# else swap 2 and 3
Ax,Ay,Cx,Cy,Bx,By,Dx,Dy = rectList[:]
# repeat
v12 = (Bx-Ax,By-Ay,0)
v13 = (Cx-Ax,Cy-Ay,0)
v14 = (Dx-Ax,Dy-Ay,0)
z1 = crossProduct(v13,v12)[2]
z2 = crossProduct(v13,v14)[2]
if z1*z2 < 0 : # if two z values have different sign, they are in order
return [Ax,Ay,Bx,By,Cx,Cy,Dx,Dy]
# else swap 3 and 4
Ax,Ay,Bx,By,Dx,Dy,Cx,Cy = rectList[:]
# repeat
v12 = (Bx-Ax,By-Ay,0)
v13 = (Cx-Ax,Cy-Ay,0)
v14 = (Dx-Ax,Dy-Ay,0)
z1 = crossProduct(v13,v12)[2]
z2 = crossProduct(v13,v14)[2]
if z1*z2 < 0 : # if two z values have different sign, they are in order
return [Ax,Ay,Bx,By,Cx,Cy,Dx,Dy]
else: raise Exception("Couldn't fix the rectangle")
答案 0 :(得分:2)
从第1点到第2点制作一个矢量。
从第1点到第3点制作一个矢量。
从第1点到第4点制作一个矢量。
计算向量1-> 3和1-> 2的叉积的z分量。
计算向量1-> 3和1-> 4的叉积的z分量。
如果这两个z有不同的符号(一个是负面的而另一个是正面的),那么你的点数就是正确的。
如果它们没有顺序,重复以上所有,首先交换点3和2.如果这还不够,那么在原始列表/数组中交换点3和4。
答案 1 :(得分:1)
我知道这是一个僵尸问题,但我找不到相关的新问题。所以我会发布这个,以防它帮助某人。
这是我用过的算法。它依赖于以下假设:
注意:它使用numpy和scikit-image坐标约定:(Y,X),左上角有(0,0)。
import numpy as np
def sorted_rect(vec):
# returns vec in clockwise order, starting with topleft
normd = vec - np.average(vec,axis=0) # vertices relative to centroid
tl_idx = np.argmax(np.dot(normd,np.array([-1,-1]))) #index of top left vertex
clockwise = np.cross(vec[(tl_idx+1) % 4] - vec[tl_idx],
vec[tl_idx] - vec[tl_idx-1]) > 0
return np.roll(vec,-tl_idx,axis=0) if clockwise else np.roll(vec,-1-tl_idx,axis=0)[::-1]