下面是2个矩形。给定矩形顶点的坐标 - (x1,y1)...(x8,y8),如何重叠区域的面积(下图中的白色)?
请注意:
答案 0 :(得分:16)
由于您声明矩形可能未对齐,因此可能的答案可能是空白,点,线段或具有3-8个边的多边形。
执行此2d boolean
操作的常用方法是选择边的逆时针排序,然后评估关键点(交叉点或拐角)之间的边缘线段。在每个交叉点,您可以在第一个矩形的边缘段与第二个矩形的边缘之间切换,反之亦然。您始终选择上一段左侧的细分。
有很多细节,但基本算法是找到所有交叉点并使用适当的数据结构在它们的边缘对它们进行排序。选择一个交叉点(如果有),并选择一个远离该交叉点的线段。找到所选起始段左侧的另一个矩形的片段。在图片中,我们选择交叉点a上的绿色段(在箭头所示的方向上)作为参考段。右侧另一个矩形的片段是从 a 到 b 的片段。将其用作下一个参考段,并选择其左侧的绿色段。这是从 b 到 c 的细分市场。以相同的方式查找段 cd 。下一个分段是从 d 到角落,因此角也位于交叉点的顶点列表中。从玉米开始,我们回到 a 。
要每次选择左侧,可以使用方向矢量坐标的确定来满足边缘。如果有序有向边对的行列式是正的,那么你就是正确的方法。
现在您已经拥有交叉点多边形的顶点,您可以使用surveyor's formula来获取该区域。
我要留给你的一些细节是:
如果一个角与另一个三角形的边或顶点重合,该怎么办?
如果没有十字路口怎么办? (一个矩形在另一个内部,或者它们是不相交的 - 您可以使用多边形点检查来解决这个问题。请参阅Wikipedia article on polygons。
如果交叉点是单个点或段,该怎么办?
答案 1 :(得分:7)
您可能会发现另一种有趣的方式,但在这种情况下可能不适用,那就是:
最终解决方案是边界框的面积乘以两个矩形内的点数然后除以数字 重复步骤2,或以公式的形式:
intersection_area = bounding_box_area * num_of_dots_inside_both / num_of_repetitions
当重复次数较多时,结果当然会更精确。顺便说一句,这种方法称为蒙特卡罗方法。
答案 2 :(得分:1)
您可以通过求解图的所有对边的交点方程来计算交点: / frac {x - a} {b - a} = / frac {x - c} {d - c}
您以这种方式获得的积分可能位于paralelepide的两侧,但它们一定不能。您必须检查通过求解方程获得的交点是否位于图的两侧。如果他们这样做,你可以计算伸展到两个数字内部的图形边长,并通过取多个来计算交点的平方。
我想我的方法听起来有点过于复杂,但这是我想到的第一个想法。
答案 3 :(得分:0)
用三角形而不是矩形来思考问题可能会有所帮助。在空间中找到三个点的三角形区域是相对简单的。
您可以通过三角形区域的总和减去矩形区域来找到相交区域,如下图所示。
基本上它变为triangulation problem。
有一个很好的介绍here,其中有一些关于数据结构和算法的指针。
编辑:
您可以重复使用一些free triangulation libraries。
如果你知道你开始使用的两个三角形的面积,你可以找到矩形的并集的总面积,因此交点将是两个矩形的总面积 - 联合区域。
答案 4 :(得分:0)
如果您碰巧使用 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;
}
我的代码:公共领域
答案 5 :(得分:0)
也许你需要使用opencv。使用fillPoly()函数生成一个矩形。确保填充矩形为白色(255,255,255)。然后使用copyTo()函数,您将获得重叠区域。然后检查每个像素的值,如果它是白色,那么+1。