如何确定一组矩形是否包含两个有重叠区域的人?

时间:2014-08-04 03:11:35

标签: c++ c algorithm computational-geometry

struct Rect
{
double left, right, top, bottom;
};

std::vector<Rect> vec;

现在我们有N(N> 1000)个矩形,什么是一个有效的算法来确定它们中的任何两个是否重叠?

更新: 所有这些矩形都与坐标系平行。

4 个答案:

答案 0 :(得分:5)

您可以通过两个段来表示矩形:打开段(x1,y1)到(x1,y2)和关闭段(x2,y1)到(x2,y2),其中x1&lt; x2和y1 < Y2

首先,我们可以通过 x坐标在O(nlogn)时间内对所有这些片段进行排序。

其次,我们逐个处理每个细分,如果我们遇到一个开放细分,我们会将该细分中的区间(y1,y2)添加到interval tree中,如果遇到的话一个关闭的段,从树中删除它。对于我们添加的每个段,我们可以查询树以查看树中有多少段与该段重叠,这也是与该矩形的开放段重叠的矩形的数量。每个查询的时间复杂度O(logn)。

因此,我们将使用O(nlogn)算法。

答案 1 :(得分:0)

一个想法是维护一个水平使用范围的集合,以及一个垂直使用范围的集合。添加一个新的矩形,调用它与水平H重叠的矩形,并同样调用V垂直。如果集合H和V的交集是非空的,则它们是与2D重叠的矩形。

直到第一次2D重叠我认为这将在O(n log n)中执行,前提是范围适当地表示,某种排序结构。

答案 2 :(得分:0)

一种粗略的方法是将坐标空间划分为D * D网格,然后创建一个与每个区域重叠的矩形矢量二维数组:

std::vector<Rect*> grid[D][D];

例如,您可能有一个20x20网格,其中一些1000多个矩形位于单个网格坐标内部,而另一些则与许多网格元素重叠。尽管如此,通过对D进行一点试验和误差调整,您可以在每个vector中获得平均5-50个矩形(取决于它们在大小上的大小差异),然后您可以强制搜索重叠。

如果您想进一步优化:

  • 如果任何矩形完全覆盖网格区域,则可以在向量中保留单个nullptr,每个矩形比较短路
  • 您可以体验不同尺寸矩形的单独网格 - 如果vector不是empty() <,则完全覆盖网格坐标的较大矩形会知道重叠/ LI>

(值得注意的是,如果你有一个重复添加新矩形的矩形体,那么值得投入分拣,合并/简化重叠矩形,索引等的努力量会大不相同,想要测试每个矩形与任何先前的矩形重叠。想要确切地知道哪些矩形重叠是另一个复杂性(上面的暴力步骤碰巧满足)。我把问题意味着有一组未分类的矩形用于需要一次性的真/假是否有任何重叠的答案。)

答案 3 :(得分:0)

我觉得很提及RHGüting和W Schilling,“用于矩形交叉问题的实用分治算法”,信息科学42(1987)。
 Pham Trung的答案(plane sweep)遵循的策略更有可能更快地实现设定问题,分而治之与适合“在线查询”的数据结构密切相关,例如,“对于给定的一组轴对齐的矩形,与这一个相交的子集是什么?“