如何设计一种算法来在屏幕上排列(可调整大小的)窗口以覆盖尽可能多的空间?


20

我想编写一个简单的程序,该程序接受一组窗口(宽度+高度)和屏幕分辨率,并在屏幕上输出这些窗口的排列,以使窗口占用最大的空间。因此,可以在保持output size >= initial size纵横比的同时调整窗口的大小 。所以对于窗口i,我希望该算法返回一个元组(x,y,width,height)

我相信这可能是2D背包的变形。我曾尝试遍历整个网络的结果,但是它们大多数都有很多背景(并且没有实现),这使我难以理解。

我对最快的算法不太感兴趣,但对满足我的特定需求的实用工具却更感兴趣。


1
我想,如果您要调整窗口的大小,那么您并不是在“保持其初始大小”,而只是“保持其宽高比”。
Emre 2012年

1
您可以调整一个窗口的大小以覆盖屏幕,这是什么问题?

2
我同意Saeed的评论。您需要其他限制,例如最小尺寸,如果要排除平凡的解决方案,则需要最大程度地减小尺寸总和。注意:数学家似乎将平铺问题称为方差
拉斐尔

1
也许更好地说,您想要最大化最小可见窗口面积并最小化最大可见窗口面积,但是是否允许冲突?请编辑您的问题以使其没有错误,考虑当前的问题陈述并不容易。

2
w ^minwWsize(w)W

Answers:


9

尽管您的问题并未说明,但我假设您不希望窗口重叠。

解决此问题的一种方法是使用约束求解器,例如Choco。只需简单地写下编码问题的约束条件,调整求解器以一种明智的方式运行,然后使其运行即可。这意味着您需要做的所有思考都将用于寻找编码问题的好方法,而不是设计算法以及进行编程和调整。这是部分答案,可以帮助您入门。

假设屏幕尺寸为 x。xmax×ymax

对于每个窗口,您将拥有一组变量和约束X ÿ ħ 瓦特Wixi,yi,hi,wi

  • xi,yi,hi,wi0
  • xi+wixmax
  • yi+hiymax
  • 也许还限制了窗口的最小大小,例如等。hi100
  • 宽高比约束:如果宽高比为3:4,则约束可能类似于,其中是一些小的非零误差项,以允许非完美窗口大小,否则您将过度约束该问题。ε4hiϵ3wi4hi+ϵϵ

现在,您需要注意窗口重叠。对于每对窗口,其中,您将生成如下约束,该约束捕获中没有出现。对于,生成约束: i j W j W ix y { x jy jx j + w jy jx jy j + h jx j + w jy j + h jWi,WjijWjWi(x,y){(xj,yj),(xj+wj,yj),(xj,yj+hj),(xj+wj,yj+hj)}

  • ¬(xixxi+wjyiyyi+hj)

到目前为止指定的约束条件仅描述了不重叠的窗口,这些窗口不溢出屏幕的侧面,满足一些最小的尺寸约束,并保留其长宽比。

为了获得良好的匹配度,您需要指定一个指标,以反映出良好布局的含义。一种可能性是假设您要使窗口大小大致相等和/或要最小化“空白”。我不认为可以使用Choco来指定它,但是可以通过其他约束解决方案来解决(其他人可以在这里提供帮助)。

Choco确实允许最大化最大化指定为单个变量的目标函数。基于此想法,您可以最大化以下内容:

  • i(hi+wi)

通过编写约束并告诉Choco最大化。c o s tcost=i(hi+wi)cost


这看起来很有希望,我一定会和Choco一起玩,看看它是如何工作的以及运行的速度。
daniel.jackson 2012年

但是为什么要这样概括呢?我认为您可以将约束条件表述为线性不等式,这意味着您拥有的是线性规划程序。
Suresh'4

@Suresh:随时详细说明。我没有立即看到如何。
戴夫·克拉克2012年

1

我开始编写蛮力解决方案的原型,希望可以对其进行优化以使其实用。

首先,一些定义:令为所有窗口的集合。每个窗口由x,y坐标以及宽度和高度的组成。用最小的宽度和高度初始化窗口。瓦特X 瓦特ÿ 瓦特瓦特瓦特ħ 瓦特Wwxw,yw,ww,hw

该算法的输入是屏幕,它具有宽度和高度以及窗口列表。S

它大致如此工作:

void fit(W, S, i, n, result)
    if i == n
        if S.score() < result.score()
            result = S
        return

    w = W[i]
    foreach x, y in S.coordinates()
        set w position to (x, y)
        while S.put(w) # check that w doesn't overlap with S's other windows and add it
            fit(W, S, i+1, n, result)
            S.windows.pop()
            w.grow()
        w.restoresize()

有几件事需要改进:

  • S.coordinates()现在非常慢。它迭代所有点,S.width x S.height并检查每个点是否在S的窗口之一中。

  • S.put()通过执行Dave答案中提到的测试,检查其参数是否与S的其余窗口重叠。也许可以通过使用间隔树来改善?

  • S.score()当前返回,这只是所有窗口的面积。它需要考虑其他变量以产生更好的布局。wS.windows(hwww)

  • 上面的函数需要尝试所有排列以获得最佳结果。W

我目前正在尝试找出一种合适的数据结构来表示屏幕及其窗口,它需要支持以下查询:

  • 返回坐标列表,可以在其中放置给定窗口而不与其他窗口重叠
  • 在位置x,y处插入窗口(已验证它没有重叠)
  • 返回所有窗口
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.