布置重叠的矩形

时间:2010-01-01 22:14:16

标签: algorithm user-interface qt layout

我正在尝试布局一堆重叠的矩形,如下所示:

alt text http://img690.imageshack.us/img690/209/picture1bp.png

我想到的2遍算法大致是:

// Pass 1 - Move all rectangles to the right until they do not overlap any other rectangles
rects = getRectsSortedOnTopLeft(); // topmost first, all rects same size
foreach(rect in rects)
{
   while(rect.collidingRects().size() != 0)
   {
       rect.x += RECT_SIZE;
   }
}

这(可能)最终会出现如下矩形: alt text http://img685.imageshack.us/img685/9963/picture2bc.png

这在美学上并不令人愉悦,所以我想到了第二遍,它会让所有人从最顶层开始再次离开:

// Pass 2
foreach(rect in rects)
{
    while(rect.x >= LEFT_MARGIN)
    {
        assert(rect.collidingRects().size() == 0);
        rect.x -= RECT_WIDTH;
        if(rect.collidingRects().size() != 0)
        {
           rect.x += RECT_WIDTH;
           break;
        }
    }
}

我认为这最终应该如下所示(在实践中看起来完全正确):

alt text http://img511.imageshack.us/img511/7059/picture3za.png

但是,我对这个算法很谨慎,因为我不确定它是否能在所有情况下正确布局,而且可能非常慢。你认为这个算法可以工作吗?你能就更好的算法提出一些建议吗?

2 个答案:

答案 0 :(得分:3)

我认为这个问题是多项式的复杂性。假设您的示例仅限于在任何给定点重叠的两个矩形不是问题的真正限制,您需要尝试将矩形向右碰撞的每个可能顺序,以便产生最佳(最小宽度)结果。这是一种空间打包问题,除非你的数据集小到足以暴力破解,否则它们都很难。

但是,您的伪代码可能会有一些小的改进,这会在很多情况下改善其性能。

考虑这个期望的最终结果:

A
A C
A C E
A C E
B C E
B D E
B D F
B D F
  D F
    F

(其中一个字符的所有四个都是一个矩形)

你的第一个传球会将除A以外的所有东西移到右边,形成一个楼梯。然后在第二遍中你的代码会拒绝将B移动到左边距,因为第一次移动它会与E重叠。你需要做的是从左边缘开始并检查你可以移动的最左边的位置传递2中的矩形。

伪代码:

// Pass 1 - Move all rectangles to the right until they do not overlap any other rectangles
rects = getRectsSortedOnTopLeft(); // topmost first, all rects same width
foreach(rect in rects)
    while(rect.collidingRects())
        rect.x += RECT_WIDTH;
// Pass 2 - Move all rectangles to the leftmost position in which they don't overlap any other rectangles
foreach(rect in rects)
    for(i=LEFT_MARGIN; i+=RECT_WIDTH; i<rect.x)
    {
        o = rect.x;
        rect.x = i;
        if(rect.collidingRects())
            rect.x = o;
    }

答案 1 :(得分:2)

您可以使用基于物理的方法,其中块是刚体,位于左侧:

不,这不会产生最好的结果,但是看过你的截屏我认为在交互式程序中使用它会非常直观,并且它可能是合适的:)