Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 求点的顺序以形成四边形_Algorithm_Geometry - Fatal编程技术网

Algorithm 求点的顺序以形成四边形

Algorithm 求点的顺序以形成四边形,algorithm,geometry,Algorithm,Geometry,在给的时候,我遇到了,检查平行四边形,然后是直角。这是可行的,但前提是输入的点按一定顺序排列。也就是说,P1和P3必须彼此“相反”,而不是相邻 所以,问题来了。如果输入的四个点可以是任意顺序,您如何对它们进行排序,使它们以“正确”的顺序形成四边形 我能想到的最简单的方法是: for each valid permutation of points[]{ // see below for "valid" generate line segment for: points[0

在给的时候,我遇到了,检查平行四边形,然后是直角。这是可行的,但前提是输入的点按一定顺序排列。也就是说,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、1
    2
    是否跨越三角形(如果它们是共线的,则四边形也退化)
  • 检查以下线段的交点:
  • 如果它们都不相交,则四边形是非凸的


    否则,您应该正好有一个相交案例。您在那里找到了相反的顶点。

    实现一个名为isParallelAndEqual(p0、p1、q0、q1)的方法。这将检查线p1-p1和q0-q1是否平行且长度相等

    给定a、b、c和d点,最终结果如下所示:


    如果ParallelandEqual(a,b,c,d)|如果ParallelandEqual(a,c,b,d)

    你不能简单地检查以下所有内容,直到找到一个是正确的吗?(即,检查彼此相对的P1点)

    对于方形变量,如果它们恰好是轴对齐的,您可以这样做:(即,相反的点是没有共同坐标的点)

    每个排列有六个段到段的检查,因此总共有18个比较

    您不需要检查所有的段:检查段
    [0-2]
    [1-3]
    (即两条对角线)是否相交就足够了。您需要检查线段是否相交,而不是线段所属的直线,即线段外的交点不计算在内

    一旦您确定了起点“A”,您将得到六种可能的排列:

    其中两个(
    A-B-D-C
    A-C-D-B
    )是好的;剩下的四个是坏的。您只需两张支票即可获得一张好支票:

    • 检查初始排列;如果它是好的,就保留它;否则
    • 交换点1和2,并检查排列;如果它是好的,就保留它;否则
    • 恢复到原始排列,交换点2和3,并保持该排列;这肯定是“好的”

    这个问题是专门针对四边形的吗?对于正方形问题,您希望所有四边形都有一个通用的解决方案,还是可以?最好是通用的解决方案。这个问题一开始是“如何找出如何把它们放到正方形问题中”,但我猜它可能还有其他有用的应用。我有一个愚蠢的问题:我们谈论的是2D点,对吗?@Bicker是的,2D只是为了这个问题。我更喜欢四边形的一般解,不一定是平行四边形。但我同意这是有用的。在一般四边形中,答案可能是模糊的。考虑一个情况,你在任何地方都有3个点,而第四点在前三点规定的三角形内。在这种情况下没有确切的答案(或者,所有答案的组合都是有效的)真的,我想我只是指凸的。好的观点,还有一些我没有考虑过的。如果
    3,0,1
    是共线的(按那个顺序),它不会看到
    [1,3]
    [0,2]
    相交吗?这是我在纸上提出的第一个反例,但我担心可能还有其他反例。我想我可以检查所有点组合的共线性,但是…@Geobits我认为这取决于交叉点检查。如果你使用叉积,找到边界案例不是很容易吗?(在
    [0,1]
    中表示交叉点,所以0或1表示边界情况?)。对于叉积,如果使用浮点数学,必须非常小心。有效/退化四边形之间的差异可能非常小,而“精确为零”的效果不太好。现在我想,你的第一点最有意义。然而,第二种方法拒绝旋转的正方形。轴对齐方法是我想到的第一件事,但它确实限制了它的实用性。然而,+1。我不知道我的大脑是怎么跳过这个事实的,我可以跑三次方程式。当然,这实际上只适用于正方形/平行四边形问题,而不是一般的四边形。这是有意义的。两次排列检查,每次一次交叉检查。我认为它不可能比这简单得多,注意ABDC=ACDB,ABCD=ADCB和ACBD=ADBC。加上第四条线(第四点和第一点之间的线),你应该会看到它。@Dukeling Right,我故意跳过了方向对称(顺时针和逆时针),以说服自己该图涵盖了所有六种可能性。
    [0, 3] and [1, 2]
    [1, 3] and [0, 2]
    [2, 3] and [0, 1]
    
    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