【问题标题】:Find If 4 Points Form a Quadrilateral求 4 个点是否形成一个四边形
【发布时间】:2012-03-01 08:45:31
【问题描述】:

谁能告诉我一个算法来编写一个函数,如果 4 个点形成一个四边形,则返回 true,否则返回 false?积分不分先后。

我尝试检查 4 个点的所有排列,看看是否有 3 个点形成一条直线。如果有3个点形成一条直线而不是四边形。但后来我意识到没有办法告诉订单。然后我挣扎了几个小时的思考和谷歌搜索没有结果:(

我已经阅读了这些问题:

  1. find if 4 points on a plane form a rectangle?
  2. Determining ordering of vertices to form a quadrilateral

但仍然找不到解决方案。在 1 的情况下,它无法检测到另一种四边形,而在 2 中,它假设点已经是四边形。有没有其他方法可以判断 4 个点是否构成一个四边形?

之前谢谢。

编辑澄清:

我将四边形定义为简单的四边形,基本上是这张图片中显示的所有形状:

带有“四边形”和“复杂”标题的形状除外。

至于“检查共线三元组”方法的问题,我尝试用这样的方式检查垂直线、水平线和对角线:

def is_linear_line(pt1, pt2, pt3):
    return (pt1[x] == pt2[x] == pt3[x] ||
            pt1[y] == pt2[y] == pt3[y] ||
            slope(pt1, pt2) == slope(pt2, pt3))

并意识到矩形和正方形将被视为直线,因为点的斜率将全部相同。希望这能解决问题。

【问题讨论】:

  • 如何定义四边形?请更详细地解释检查共线三元组有什么问题。
  • @tom:我已经编辑了问题以进行澄清。如果还有什么不清楚的地方,请告诉我。谢谢。
  • 谢谢。按照这个定义,只要可以选择边,任意四个点都可以构成一个四边形。
  • @tom 是对的。问题应该是“如果4个点可以形成一个四边形”。

标签: algorithm geometry


【解决方案1】:

这是为了检查一个四边形是否是凸的。如果它是一个简单的四边形,则不是。

我在objective-c中确实喜欢这个https://github.com/hfossli/AGGeometryKit/

extern BOOL AGQuadIsConvex(AGQuad q)
{
    BOOL isConvex = AGLineIntersection(AGLineMake(q.bl, q.tr), AGLineMake(q.br, q.tl), NULL);
    return isConvex;
}

BOOL AGLineIntersection(AGLine l1, AGLine l2, AGPoint *out_pointOfIntersection)
{
    // http://stackoverflow.com/a/565282/202451

    AGPoint p = l1.start;
    AGPoint q = l2.start;
    AGPoint r = AGPointSubtract(l1.end, l1.start);
    AGPoint s = AGPointSubtract(l2.end, l2.start);

    double s_r_crossProduct = AGPointCrossProduct(r, s);
    double t = AGPointCrossProduct(AGPointSubtract(q, p), s) / s_r_crossProduct;
    double u = AGPointCrossProduct(AGPointSubtract(q, p), r) / s_r_crossProduct;

    if(t < 0 || t > 1.0 || u < 0 || u > 1.0)
    {
        if(out_pointOfIntersection != NULL)
        {
            *out_pointOfIntersection = AGPointZero;
        }
        return NO;
    }
    else
    {
        if(out_pointOfIntersection != NULL)
        {
            AGPoint i = AGPointAdd(p, AGPointMultiply(r, t));
            *out_pointOfIntersection = i;
        }
        return YES;
    }
}

【讨论】:

    【解决方案2】:

    除非您使用比您已经执行的操作更昂贵的操作,否则无法在同一操作中确定顶点顺序和是否存在四边形。

    【讨论】:

    • 手术费用不是问题。有办法吗?
    【解决方案3】:

    检查共线三元组(就像您所做的那样)将排除四个点形成三角形或直线的情况。

    排除复杂的四边形(交叉边):

    如果 AB 和 CD 的交点(如果有)位于 A 和 B 之间,则由 A、B、C 和 D 点组成的四边形是复数,BC 和 DA 也是如此。

    【讨论】:

      【解决方案4】:

      除了 4 点之外,您还有更多的输入吗?因为如果 4 个点通过了您的测试,它们总是可以形成 3 个不同的四边形,有时属于不同的族。例如,取一个正方形,添加 2 条对角线并删除边。

      因此,只有 4 个点作为输入,您无法做得比您已经在做的更好。

      【讨论】:

      • 不,只有 4 个输入。那就没有办法改进了吗?
      • 虽然我晚了十年,但有什么进展吗?
      【解决方案5】:

      设 A、B、C 和 D 为四个点。您必须假设边是 A-B、B-C、C-D 和 D-A。如果你不能做出这样的假设,那么这四个点总是会形成一个四边形。

      if (A-B intersects C-D) return false
      if (B-C intersects A-D) return false
      return true
      

      【讨论】:

        【解决方案6】:

        首先,使用距离公式找出所有边和对角线的尺寸: This.

        接下来,使用以下公式找到所有角度: This

        参考来自:https://algorithmdotcpp.blogspot.com/2022/01/find-type-of-quadrilateral-with-given-points.html

        python中的代码:

        # array
        # read 8 number
        points = list(map(int,input().split()))    
        
        # create separate variable for coordinates
        xa = points[0]
        ya = points[1]
        xb = points[2]
        yb = points[3]
        xc = points[4]
        yc = points[5]
        xd = points[6]
        yd = points[7]
        
        # edge of quadrilateral using edge formula
        # finding edge using distance formula.
        a = math.sqrt((xb - xa) * (xb - xa) + (yb - ya) * (yb - ya))
        b = math.sqrt((xc - xb) * (xc - xb) + (yc - yb) * (yc - yb))
        c = math.sqrt((xd - xc) * (xd - xc) + (yd - yc) * (yd - yc))
        d = math.sqrt((xa - xd) * (xa - xd) + (ya - yd) * (ya - yd))
        
        # diagonal of quadrilateral
        # find diagonals.
        diagonal_ac = math.sqrt((xc - xa) * (xc - xa) + (yc - ya) * (yc - ya))
        diagonal_bd = math.sqrt((xd - xb) * (xd - xb) + (yd - yb) * (yd - yb))
        
        # angles
        # angles of quadrilateral
        # find angle using angle formula.
        A = math.acos((a * a + d * d - diagonal_bd * diagonal_bd) / (2 * a * d))
        B = math.acos((b * b + a * a - diagonal_ac * diagonal_ac) / (2 * b * a))
        C = math.acos((c * c + b * b - diagonal_bd * diagonal_bd) / (2 * c * b))
        D = math.acos((d * d + c * c - diagonal_ac * diagonal_ac) / (2 * d * c))
        

        现在我们可以使用 if-else 条件来判断四边形或四边形的类型是否找不到。

        # if angles are equal means(90*)
        if (A == B and A == C and A == D):
        
            # if edge size are equal
            if (a == b and a == c and a == d):
                # square
                print("Quadrilateral is square...\n")
                print("area of square :", a * a)
            
            # else
            else:
                # rectangular
                print("Quadrilateral is rectangular...\n")
                print("area of square :", a * b)
            
        
        # angles are not equal but edges are equal
        elif (a == b and a == c and a == d):
            # diamond
            print("Quadrilateral is diamond(Rhombus)...\n")
        
        # opposite edges(sides) are equal
        elif (a == c and b == d):
            # parallelogram
            print("Quadrilateral is parallelogram...")
        
        else:
            print("Quadrilateral is just a quadrilateral...\n")
        

        【讨论】:

          猜你喜欢
          • 2022-01-23
          • 2012-08-22
          • 1970-01-01
          • 2011-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-16
          • 1970-01-01
          相关资源
          最近更新 更多