给定许多水平和垂直线,如何找到其中有任何子矩形的所有矩形?

时间:2013-04-24 15:13:39

标签: algorithm rectangles

我有很多水平和垂直线组成矩形,例如在这个例子中。

Picture of horizontal and vertical lines

是否有算法或代码可以找到每个不包含另一个矩形的矩形。我的意思是,这个图像中最大的矩形不是我正在寻找的矩形,因为它内部包含其他矩形。

我要找的矩形必须是空的。我列出了每一行的起点和终点,如(a,b)到(c,d)。我想要一个矩形列表(x,y,w,h)或等价物。

请注意,某些线条的直线与它们相交,例如,此图像中最宽矩形的顶线是一条线,它有一条相交的垂直线向下。

4 个答案:

答案 0 :(得分:2)

我认为不同的陈述可以帮助您解决问题。例如,考虑大矩形(末端没有块)。有四个唯一的x和y坐标,对它们进行排序和索引。图示它看起来像这样:

enter image description here

如果坐标(x_i, y_j)上有一个矩形的角落,请将其放入矩阵中,如下所示:

__|_1__2__3__4_
1 | x  x  0  x
2 | x  x  0  0
3 | 0  x  x  x
4 | x  x  x  x

现在根据定义,真实空间中的矩形是矩阵坐标上的矩形。例如,(3,2) (3,4) (4,4), (4,3)处有一个矩形,但它不是“基础”矩形,因为它包含一个子矩形(3,3) (3,4), (4,4), (4,3)。这里很容易看到递归算法,并且为了增加速度,使用memoization来防止重复计算。

答案 1 :(得分:2)

A sweep-line algorithm ...

需要的结构:

  • V =一组垂直线,按x坐标排序。

  • H =水平线的所有起点和终点的集合(并且每个点保持对线的引用)并按x坐标排序。

  • CH =一组(最初为空)按当前水平线排序(按y坐标)。

  • CR =一组当前矩形的排序(按y坐标)。这些矩形将具有左,上和下坐标,但还不是右坐标。请注意,此集合中不会重叠。

<强>算法:

同时从左到右处理V和H.

每当遇到水平线的开始时,将线添加到CH。

每当遇到水平线的末端时,请从CH中删除它。

每当遇到垂直线时:

  • 从CR中删除与该线重叠的所有矩形。对于所有删除的矩形,如果它完全包含在该行中,请将其大小与目前为止的最佳矩形进行比较,并在更好的情况下存储它。

  • 在行的底点和顶点之间迭代处理CH中的每个元素,如下所示:

    • 向CR添加一个矩形,最后一个处理点为底部,当前点为顶部,垂直线的y坐标为左侧。

完成。

注意:

当水平起点或终点或垂直线的x坐标相等时,必须维持的以下顺序:

x of horizontal start < x of vertical line < x of horizontal finish

否则你会错过矩形。

答案 2 :(得分:1)

这些问题主要由一些标准的Computational Geometry算法来回答。我可以为这个特殊问题考虑vertical sweep line算法。

假设一个矩形由一对点(p1, p2)表示,其中p1是左上角,p2是右下角。并且一个点有两个属性(可以p.xp.y进行访问。)

这是算法。

  1. 对所有点对进行排序 - O(n log n)
  2. 初始化名为sweep line status的列表。这将保留到目前为止遇到的所有矩形,即alive。还初始化另一个名为event queue的列表,用于保存即将发生的事件。此event queue目前包含所有rectagles的起点。
  3. 处理事件,从event queue中的第一个元素开始。
    • 如果事件是start point,则将该矩形添加到sweep line status(按y坐标排序)(在O(log n)时间内)并将其右下角添加到event queue在适当的位置(按点排序)(再次在O(log n)时间内)。当您将其添加到sweep line status时,您只需要检查此点是否位于sweep line status中位于其上方的矩形中。如果它确实在里面,那么这不是你的矩形,否则,将它添加到你需要的矩形列表中。
    • 如果事件是终点,只需从sweep line status中删除相应的矩形。
  4. 运行时间(对于n个矩形):

    • 排序需O(n log n)
    • 事件数量= 2 * n = O(n)
    • 每个事件都需要O(log n)时间(适用于event queue以及sweep line status的插入。因此总计为O(n log n)

    因此,O(n log n)

    有关详细信息,请参阅Bentley–Ottmann algorithm。以上只是对此的一个简单修改。

    编辑:

    刚刚意识到输入是根据线段,但由于它们总是形成矩形(根据问题),预处理的线性遍历可以将它们转换为矩形(点对)形式。

答案 3 :(得分:0)

您的所有线条是否与x轴或y轴平行?或者,你的所有线条是平行还是垂直?

从你给出的例子我假设你所有的线都与x或y轴平行。在这种情况下,你的线将是[(a,b),(a,d)]或[(a,b),(c,b)]。

无论如何,第一项任务是找到角落。这是两条垂直线相交的点集。

第二项任务是检测矩形。对于每对角,您可以检查它们是否形成矩形。

第三项任务是找出一个矩形本身是否有任何矩形。

对于第一项任务,您需要将线分为两组:垂直和水平。之后排序其中一组。防爆。根据x轴坐标对垂直线进行排序。然后你可以获取所有水平线并进行二分搜索以找到所有相交点。

对于第二项任务,考虑每对角并查看是否存在其他两个角。如果是,那么看看是否有连接所有这四个角的线。如果是,你有一个矩形。

对于第三项任务,将所有矩形放在间隔树中。之后,您可以检查两个矩形是否重叠。