在现有的非重叠矩形之间拟合矩形

时间:2015-09-25 01:04:09

标签: algorithm computational-geometry rectangles

我有一个问题,最好用计算机屏幕上的窗口来说明:创建另一个窗口,尽可能大,不与任何现有窗口重叠。

换句话说:在有限表面(一张纸或一个屏幕)上给出一组N个矩形,找到可以在这些矩形之间拟合的最大矩形。 (坐标可以是任意的,因此位图在这里不是一个可行的解决方案。)

下图显示了三个矩形(黑色)和可以安装的最大矩形(红色)。

http://www.irstafoto.se/blogmtrl/rectangle-illustration.jpg

我为此编写了一个简单的算法,它考虑了矩形使用的所有x和y坐标对。遗憾的是,它是O(N ^ 5),因为在最坏的情况下,必须针对每个其他矩形检查每个矩形候选项以进行重叠。

有什么更好的吗?



       max_area = 0;
       max_rect = nil

       xc = all rectangle x-coordinates [x1, ..., x6] in picture)
       yc = all rectangle y-coordinates (y1, ..., y6] in picture)
       xc = [0] + xc + [W]; /* W is width of area */
       yc = [0] + yc + [H]; /* H is height of area */

       sort(xc);
       sort(yc);

       for each x0 in xc
           for each x1 > x0 in xc
               for each y0 in yc
               for each y1 > y0 in yc
                       r = rect(x0,y0,x1,y1)
                       if (area(r) > max_area and !overlapping(r))
                           max_area = area(r)
                           max_rect = r

2 个答案:

答案 0 :(得分:0)

我的建议:

独立地对X和Y进行排序,以便您可以将所有角坐标映射到[0,2N]范围内的整数索引。

使用黑色填充二进制图像,其中空间由缩小坐标中的矩形占据。图像大小为(2N + 1)x(2N + 1)。

enter image description here

找到可放置在白色区域中的最大矩形。这可以在与图像区域成比例的时间内完成。 (参见文章“基于矩形列表的对象描述符:方法和算法”。)

然后对于每个最大矩形,在给定真实坐标的情况下计算实际面积,并保持最大

这应该是一个整体O(N²)程序。

答案 1 :(得分:0)

半四叉树方法怎么样?您可以创建一个具有9个属性的节点,矩形本身,4个矩形,其区域可用于节点当前矩形的北,南,东和西;最后4个节点,每个节点在相应的区域中具有子树。 Node类看起来像这样:

class node 
{
    public var nr:Rectangle;
    public var sr:Rectangle;
    public var wr:Rectangle;
    public var er:Rectangle;

    public var nn:node = null;
    public var sn:node = null;
    public var wn:node = null;
    public var en:node = null;

    public var rect:Rectangle;
}

创建新节点时,您应该使用包含当前矩形边的线条来剪切边界区域。这不是典型的四叉树。这里子节点的区域可能重叠。

另外两项基本行动。首先添加矩形。从第一个实心矩形开始,您可以创建一个节点,然后为每个剩余的矩形添加它们到树中。要向节点添加矩形,您应检查它是否与其任何区域重叠。如果是这样,将其剪辑到该区域并将其向下推到该节点。如果node为空(或null),则创建一个新节点。

最后找到一个最大的矩形。这是从根节点开始递归完成的。你应该得到覆盖所有4个区域的最大矩形。这很容易,因为您已经将它们作为节点的属性。但是有一个技巧 - 如果这个区域中有一个子节点,你应该使用这个节点最大的rect(这里是递归)。