在向an answer提供"Given four coordinates check whether it forms a square"的同时,我遇到了this answer,它检查了平行四边形,然后是直角。这是有效的,但只有当进入的点按特定顺序时才有效。即,P1和P3必须彼此“相对”,而不是相邻。
所以,问题。如果进入的四个点可以按任何顺序排列,那么如何对它们进行排序以使它们处于“正确”的顺序以制作四边形?
我能想到的最简单的事情是:
for each valid permutation of points[]{ // see below for "valid"
generate line segment for:
points[0] -> points[1]
points[1] -> points[2]
points[2] -> points[3]
points[3] -> points[0]
if any line segment crosses another // use cross product
continue
return permutation
}
我知道大多数排列都是简单的旋转(0123 == 1230
),所以我可以保持第一个点“固定”。另外,我想我可以通过仅考虑每个排列点的0
和2
中的点来减少它,因为其他两个的顺序无关紧要。例如,如果0123
是多边形,0321
也是,因为它会生成相同的段。
这让我只有三种基本排列检查:
[0,1,2,3]
[0,1,3,2]
[0,2,1,3]
每个排列都有六个段到段的检查,因此总共进行了18次比较。
我想不出有任何其他办法可以做到这一点,但似乎我错过了一些东西。有一个更好的方法吗?对于方形问题给出的答案是好的,但是如果我必须进行额外的(最多)18次检查以验证点的顺序是否正确,那么使用角间距离会更快。
答案 0 :(得分:2)
每个排列都有六个段到段的检查,因此总共进行了18次比较。
您无需检查所有细分:检查细分[0-2]
和[1-3]
(即两条对角线)是否相交就足够了。您需要检查段是否相交,而不是段所属的行,即段之外的交叉点不计算。
修正起点"A"
后,您最终会得到六种可能的排列:
其中两个(A-B-D-C
和A-C-D-B
)很好;剩下的四个都不好。只用两张支票就可以得到一个好的:
答案 1 :(得分:1)
实现一个名为isParallelAndEqual(p0,p1,q0,q1)的方法。这将检查行p1-p1和q0-q1是否平行且长度相等。
给定a,b,c和d点,最终结果如下:
ifParallelAndEqual(a,b,c,d)|| ifParallelAndEqual(a,c,b,d)
答案 2 :(得分:1)
难道你不能简单地检查以下所有内容,直到找到一个是真的吗? (也就是说,检查P1对面的点)
P3 = P1 + (P2-P1) + (P4-P1)
P2 = P1 + (P3-P1) + (P4-P1)
P4 = P1 + (P2-P1) + (P3-P1)
对于方形变体,如果它们碰巧是轴对齐的,你可以这样做:(也就是说,相反的点是没有共同坐标的那个)
if (P1.x != P3.x && P1.y != P3.y)
check P3 = P1 + (P2-P1) + (P4-P1)
if (P1.x != P2.x && P1.y != P2.y)
check P2 = P1 + (P3-P1) + (P4-P1)
if (P1.x != P4.x && P1.y != P4.y)
check P4 = P1 + (P2-P1) + (P3-P1)
otherwise return false
答案 3 :(得分:0)
执行以下操作会不会更简单:
0, 1
和2
是否跨越三角形(如果它们是共线的,则四边形也会退化)
[0, 3] and [1, 2]
[1, 3] and [0, 2]
[2, 3] and [0, 1]
如果它们都不相交,则四边形是非凸的。
否则,您应该只有一个交叉的情况。你在那里找到了相反的顶点。