【问题标题】:Area of rectangle-rectangle intersection长方形-长方形相交面积
【发布时间】:2011-11-04 15:00:18
【问题描述】:

下面是 2 个矩形。给定矩形顶点的坐标 - (x1, y1)...(x8, y8),如何计算重叠区域(下图中白色)的面积?

请注意:

  1. 点的坐标可以是任意的
  2. 矩形可能重叠也可能不重叠
  3. 当矩形不重叠或在点或线处重叠时,假设面积为 0。
  4. 如果一个矩形在另一个矩形内,则计算较小矩形的面积。

【问题讨论】:

  • 更具体地说,您的意思是 rectangles 对齐轴,对吗?
  • 平行六面体是 3 维多面体,可以有非直角相交。您的图像似乎显示了一对对齐的矩形。
  • DeepYellow:是的,你是对的。
  • Parker:抱歉我的错字,我的意思是矩形。
  • 重叠区域的面积:对,就是这个意思。

标签: c++ math computational-geometry


【解决方案1】:

既然你说矩形可能没有对齐,可能的答案可能是什么,一个点,一条线段,或者一个 3-8 边的多边形。

执行此2d boolean 操作的常用方法是选择边缘的逆时针顺序,然后评估临界点(交叉点或拐角)之间的边缘段。在每个交叉点,您在第一个矩形的边缘段和第二个矩形的边缘之间切换,反之亦然。您总是选择前一个片段左侧的片段。

有很多细节,但基本算法是找到所有交点,并使用适当的数据结构在它们的边缘上对它们进行排序。选择一个交点(如果有的话)并选择一条远离该交点的线段。找到所选起始段左侧的另一个矩形的段。在图中,我们选择交叉点a上的绿色线段(箭头方向)作为参考线段。右边的另一个矩形的线段是从 ab 的线段。将其用作下一个参考段,并选择其左侧的绿色段。那是从 bc 的部分。以相同的方式查找段 cd。下一段是从 d 到角点,所以角点也在交点的顶点列表中。从玉米地我们回到a

要每次选择左侧,请使用相交边的方向向量坐标的确定值。如果有序有向边对的行列式是正的,那么你就走对了。

现在您已经有了交集多边形的顶点,您可以使用surveyor's formula 来获取面积。

我要留给你的一些细节是:

  • 如果一个角与另一个三角形的边或顶点重合怎么办?

  • 如果没有交叉路口怎么办? (一个矩形在另一个矩形之内,或者它们不相交——您可以使用多边形中的点检查来解决这个问题。请参阅Wikipedia article on polygons

  • 如果交点是单点或线段怎么办?

【讨论】:

  • 矩形的点可能是any。因此,虽然一个矩形可能是垂直的,但另一个可能不是。
  • 在这种情况下,您不会有矩形或(正如您最初所说的“正方形”相交)。答案可能是空的,一个点、一条线段、三角形等等,最多一个八角形!所以原来的问题有很多缺陷。
  • 问题有很多缺陷:似乎是这样......我现在将更新问题。
【解决方案2】:

还有一种你可能会觉得有趣但可能不适用于这种情况的方法,那就是:

  1. 确定最小矩形(其边平行于 坐标轴)包含两个给定的矩形,让 称这个新的为边界框。
  2. 在边界框中随机选择一个点,检查它是否在两个矩形中
  3. 根据需要重复第 2 步(这取决于您想要的结果精度),并有两个计数器,一个用于 跟踪两个矩形内的点数,以及 另一个是第2步的重复次数
  4. 最终的解决方案是边界框的面积乘以两个矩形内的点数,然后除以数字 步骤 2 的重复次数,或以公式的形式:

    intersection_area = bounding_box_area * num_of_dots_inside_both / num_of_repetitions

当然,重复次数越多,结果就越精确。顺便说一下,这种方法称为蒙特卡洛方法。

【讨论】:

  • 非常有趣的方式!谢谢!
【解决方案3】:

您可以通过求解图形所有对边的交点方程来计算交点: /frac{x - a}{b - a} = /frac{x - c}{d - c}

您以这种方式获得的积分可以位于 paralelepide 的两侧,尽管它们不能。您必须检查通过求解方程获得的交点是否位于图形的两侧。如果是这样,您可以计算延伸到两个图形内部的图形边的长度,并通过取它们的倍数来计算交点的平方。

我想我的方法听起来有点过于复杂,但这是我想到的第一个想法。

【讨论】:

    【解决方案4】:

    用三角形而不是矩形来考虑问题可能会有所帮助。给定空间中的三个点,求三角形的面积相对简单。

    如下图所示,您可以通过三角形面积之和减去矩形面积来找到相交面积。

    基本上它变成了triangulation problem

    有一个很好的介绍here,其中包含一些关于数据结构和算法的指针。

    编辑:

    有一些free triangulation libraries 可以重复使用。

    如果你知道你开始的两个三角形的面积,你可以找到矩形联合的总面积,所以交点就是两个矩形的总面积 - 联合面积。

    【讨论】:

    • @DeepYellow 的回答中提到的测量员公式比减去三角形要简单得多。在一般情况下处理三角形,当图形可能看起来不像那张图片时会是一团糟。
    • 我指出了这个解决方案,因为它不需要旋转坐标。 (显示的数字是最难处理的数字之一。也就是说,它是你会遇到的最大的烂摊子。)。
    • @ckoo,我的解决方案也不需要旋转矩形。该解决方案是当 OP 有一个暗示矩形是轴对齐的绘图时。我将修改我的回复,明确表示不需要轮换。
    • 仅作记录,对于任何阅读并为此苦苦挣扎的人,不幸的是,这个答案本质上是错误的。确实有很多这样的问题,其中有一个“非常聪明”的解决方案,包括将问题变成三角形。 然而,很遗憾,矩形-矩形问题根本没有这样一个“聪明的三角形”解决方案。不幸的是,DeepYellow 给出了唯一的答案。 (除非将来有人为此发明了一个令人难以置信的算法!:))
    【解决方案5】:

    如果你碰巧使用Qt,那么交集可以计算为QPolygonF交集。 大致如此:

    QPolygonF p1,p2, intersected;
    p1 << QPointF(r1x1,r1y1) << ... << QPointF(r1x4, r1y4);
    p2 << QPointF(r2x1,r2y2) << ... << QPointF(r2x4, r2y4);
    intersected = p1.intersected(p2);
    
    float area = polyArea(intersected); // see code block below
    

    (r1 = 矩形 1,r2 = 矩形 2,分别有 4 个 x 和 y 坐标)。

    现在计算面积(使用已经提到的Shoelace formula):

    inline float polyArea(const QPolygonF& p)
    {
        //https://en.wikipedia.org/wiki/Polygon#Area_and_centroid
        const int n = p.size();
        float area = 0.0;
        for (int i=0; i<n; i++)
        {
            area += p[i].x()*p[(i+1)%n].y() - p[(i+1)%n].x()*p[i].y();
        }
        if (area < 0)
            return -0.5*area;
        else
            return 0.5*area;
    }
    

    我的代码在这里:公共领域

    【讨论】:

      【解决方案6】:

      也许你需要使用opencv。使用 fillPoly() 函数生成一个矩形。确保填充矩形为白色(255、255、255)。然后使用 copyTo() 函数,您将获得重叠区域。然后检查每个像素的值,如果是白色则+1。

      【讨论】:

        猜你喜欢
        • 2017-01-16
        • 1970-01-01
        • 2012-07-21
        • 2014-05-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-23
        • 1970-01-01
        相关资源
        最近更新 更多