我有很多水平和垂直线组成矩形,例如在这个例子中。
是否有算法或代码可以找到每个不包含另一个矩形的矩形。我的意思是,这个图像中最大的矩形不是我正在寻找的矩形,因为它内部包含其他矩形。
我要找的矩形必须是空的。我列出了每一行的起点和终点,如(a,b)到(c,d)。我想要一个矩形列表(x,y,w,h)或等价物。
请注意,某些线条的直线与它们相交,例如,此图像中最宽矩形的顶线是一条线,它有一条相交的垂直线向下。
答案 0 :(得分:2)
我认为不同的陈述可以帮助您解决问题。例如,考虑大矩形(末端没有块)。有四个唯一的x和y坐标,对它们进行排序和索引。图示它看起来像这样:
如果坐标(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)
需要的结构:
V =一组垂直线,按x坐标排序。
H =水平线的所有起点和终点的集合(并且每个点保持对线的引用)并按x坐标排序。
CH =一组(最初为空)按当前水平线排序(按y坐标)。
CR =一组当前矩形的排序(按y坐标)。这些矩形将具有左,上和下坐标,但还不是右坐标。请注意,此集合中不会重叠。
<强>算法:强>
同时从左到右处理V和H.
每当遇到水平线的开始时,将线添加到CH。
每当遇到水平线的末端时,请从CH中删除它。
每当遇到垂直线时:
从CR中删除与该线重叠的所有矩形。对于所有删除的矩形,如果它完全包含在该行中,请将其大小与目前为止的最佳矩形进行比较,并在更好的情况下存储它。
在行的底点和顶点之间迭代处理CH中的每个元素,如下所示:
完成。
注意:强>
当水平起点或终点或垂直线的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.x
和p.y
进行访问。)
这是算法。
O(n log n)
sweep line status
的列表。这将保留到目前为止遇到的所有矩形,即alive
。还初始化另一个名为event queue
的列表,用于保存即将发生的事件。此event queue
目前包含所有rectagles的起点。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
中删除相应的矩形。运行时间(对于n个矩形):
O(n log 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轴坐标对垂直线进行排序。然后你可以获取所有水平线并进行二分搜索以找到所有相交点。
对于第二项任务,考虑每对角并查看是否存在其他两个角。如果是,那么看看是否有连接所有这四个角的线。如果是,你有一个矩形。
对于第三项任务,将所有矩形放在间隔树中。之后,您可以检查两个矩形是否重叠。