矩形与矩形相交的面积

发布于 2024-12-13 17:25:48 字数 284 浏览 1 评论 0原文

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

注意:

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

在此处输入图像描述

Below are 2 rectangles. Given the coordinates of the rectangle vertices - (x1, y1)...(x8, y8), how can the area of the overlapping region (white in the figure below) be caclulated?

Note that:

  1. Coordinates of points might be any
  2. Rectangles may or may not overlap
  3. Assume area is 0 when rectangles don't overlap, or they overlap at point or line.
  4. If one rectangle is inside the other, then calculate area of smaller rectangle.

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

⒈起吃苦の倖褔 2024-12-20 17:25:48

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

执行此二维布尔运算的常用方法是选择边缘的逆时针顺序,然后评估关键点(交叉点或角点)之间的边缘段。在每个交叉点,您可以在第一个矩形的边缘段和第二个矩形的边缘之间切换,反之亦然。您始终选择前一段左侧的段。

在此处输入图像描述

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

要每次选择左侧,请使用相交边的方向向量坐标的确定值。如果有序的有向边对的行列式为正,则说明您的方向正确。

现在您已经有了相交多边形的顶点,您可以使用测量员公式 获取面积。

我留给您的一些细节是:

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

  • 如果没有交叉点怎么办? (一个矩形位于另一个矩形内部,或者它们是不相交的 - 您可以使用多边形内的点检查来解决这一问题。请参阅 关于多边形的维基百科文章

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

Since you stated that the rectangles may not be aligned, possible answers may be nothing, a point, a line segment, or a polygon with 3-8 sides.

The usual way to do this 2d boolean operation is to choose a counterclockwise ordering of the edges, and then evaluate edge segments between critical points (intersections or corners). At each intersection you switch between an edge segment of the first rectangle to an edge of the second, or visa-versa. You always pick the segment to the left of the previous segment.

enter image description here

There are LOTS of details, but the basic algorithm is to find all intersections and order them on their edges with an appropriate data structure. Choose an intersection (if there is one) and choose a line segment leading away from that intersection. Find the segment of the other rectangle to the left of the chosen starting segment. In the picture, we choose the green segment on intersection a (in the direction indicated by the arrow) as the reference segment. The segment of the other rectangle that is to the right, is the segment from a to b. Use that as the next reference segment, and choose a green segment to the left of it. That's the segment from b to c. Find segment cd the same way. The next segment is from d to the corner, so the corner is in the vertex list for the intersection as well. From the corn we get back to a.

To choose the left side each time, you use the determinate of the coordinates of the direction vectors for the edges that meet. If the determinant for the ordered pair of directed edges is positive, you're going the right way.

Now that you have the vertices of the intersection polygon, you can use the surveyor's formula to get the area.

Some of the details that I'm leaving to you are:

  • What if a corner is coincident to to an edge or vertex of the other triangle?

  • What if there are no intersections? (one rectangle is inside the other, or they are disjoint--you can use point-in-polygon checks to figure this out. See the Wikipedia article on polygons.

  • What if the intersection is a single point or a segment?

动听の歌 2024-12-20 17:25:48

还有另一种方法您可能会觉得有趣,但在这种情况下可能不适用,那就是:

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

    交集区域 = 边界框区域 * num_of_dots_inside_both /
    num_of_repetitions

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

There is another way that you may find interesting, but maybe not applicable in this case, and that is:

  1. determine the minimum rectangle( whose sides are parallel to
    coordinate axes ) that contains both of the given rectangles, lets
    call that new one a bounding box.
  2. pick a random dot that is in the bounding box and check whether it is in both rectangles or not
  3. repeat step 2 for as long as you want( it depends on the precision you want for your result ), and have two counters, one to
    keep track of the number of dots inside both of the rectangles, and
    the other which is the number of repetitions of step 2
  4. the final solution is the area of the bounding box multiplied by the number of dots inside both rectangles and then divided by number
    of repetitions of step 2, or in a form of a formula:

    intersection_area = bounding_box_area * num_of_dots_inside_both /
    num_of_repetitions

The result will, of course, be more precise when the number of repetitions is larger. By the way, this method is called Monte Carlo method.

隐诗 2024-12-20 17:25:48

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

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

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

You can calculate the intersection points by solving intersection equations for all pairs of sides of the figures:
/frac{x - a}{b - a} = /frac{x - c}{d - c}

The points that you obtain in such a fashion can lie on the sides of the paralelepide, though they must not. You have to check whether the intersection points you obtained by solving the equations lie on the sides of the figure or not. If they do, you can calculate the length of the sides of the figure that stretch out into the inside of the both figures, and calculate the square of the intersection by taking their multiple.

I guess my method sounds a bit over-complicated, but this is the first thought that came to my mind.

琉璃繁缕 2024-12-20 17:25:48

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

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

Triangulation

本质上它变成了 三角测量问题

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

编辑:

有一些您可以重用的免费三角测量库

如果您知道开始时的两个三角形的面积,则可以找到矩形并集的总面积,因此交集将是两个矩形的总面积 - 并集面积。

It may help to think of the problem in terms of triangles instead of rectangles. Finding the area of a triangle given three points in space is relatively straight forward.

You can find the intersecting area by subtracting the rectangle area by the sum of the areas of the triangles as shown in the image below.

Triangulation

Essentially it becomes a triangulation problem.

There is a good intro here with some pointers on data structures and algorithms.

EDIT:

There are some free triangulation libraries that you could reuse.

If you know the area of the two triangles you are starting off with you can find the total area of the union of the rectangles, so the intersection would be the total area of both rectangles - the union area.

谎言 2024-12-20 17:25:48

如果您碰巧使用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 坐标)。

现在计算面积(使用已经提到的鞋带公式):

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;
}

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

If you happen to use Qt then the intersection can be computed as QPolygonF intersection.
Roughly as so:

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 = rectangle 1, r2 = rectangle 2, with 4 respective x and y coordinates).

Now compute the area (using the already mentioned 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;
}

My code here: public domain

故人爱我别走 2024-12-20 17:25:48

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

Maybe you need to use opencv. Use the fillPoly() function to generate a rectangle. Make sure the fill rectangle is white (255, 255, 255). Then use the copyTo() function and you will get the overlap area. Then check the value of each pixel , if it is white then +1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文