关于 2d:是否有用于在窗口中自动调整大小和分布正方形/矩形的算法?

Is there an algorithm for automatic sizing and distributing squares/rectangles in a window?

我试图找到这样的算法,但到目前为止我没有成功,希望你能帮助我。提前致谢!

所以我的问题是:我有一个画布。通过单击一个按钮,我可以创建一个矩形。当我有一个矩形时,它被绘制以占据大部分画布。当我再次按下它时,会出现一个新的矩形,然后重新绘制两个矩形以占据几乎一半的可用画布。然后创建第三个矩形,将三个矩形分布在两排,以保持每个矩形的长宽比例一定,尽可能多的占据画布。依此类推,对于 n 个矩形,请参见图片:

image

是否有任何众所周知的算法可以做到这一点?

谢谢!


您的矩形都具有相同的大小,因此您的任务是为您的布局找到最佳的行数和列数。布局由边界矩形、矩形数量 k 和首选宽高比 α* 以及矩形之间的间隙 d 组成:

1
2
3
4
5
6
7
8
9
const box = {
    count: 7,
    alpha: 1.2,
    gap: 8,
    nrow: 0,        // to be determined ...
    ncol: 0,        // ...
    width: 0,       // ...
    height: 0,      // ...
};

一个非常简单的算法会根据输入找到列数 m 的第一个猜测值,然后尝试几个 m 以找到最大面积,同时保持合理的纵横比。

你的总面积是 A = W · H。一个盒子的面积是 a = w · h 或 a = h / α,其中 α = w / h。理论最大面积(如果间隙为 0)是 a* = A / k,其中 k 是矩形的数量。您可以使用它来估计 w 的第一个猜测,然后估计列数 m.

我们优化的"分数"是必须最大化的区域。为了不允许出现令人不快的纵横比,我们通过将分数除以误差的平方 (α ? α*)2 来合并当前纵横比 α。

这是一种可以实现的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function layout(canvas) {
    let A = canvas.width * canvas.height;
    let a = A / box.count;
    let x = Math.sqrt(a * box.alpha);
    let m = (canvas.width / x) | 0 - 2;

    if (m < 1) m = 1;

    let best = 0.0;

    for (;;) {
        let n = (((box.count - 1) / m) | 0) + 1;
        let w = (canvas.width - (m - 1) * box.gap) / m;  
        let h = (canvas.height - (n - 1) * box.gap) / n;

        if (h < 0) h = 0;
        if (w < 0) w = 0;

        let alpha = w / h;
        let area = box.count * (w + box.gap) * (h + box.gap);
        let dalpha = alpha - box.alpha;
        let score = area / (dalpha * dalpha);

        if (score < best) break;

        box.width = w;
        box.height = h;
        box.ncol = m;
        box.nrow = n;

        best = score;
        m++;
    }
}

当然还有改进的余地,例如在猜测第一枪时。您可以在 jsbin 上进行粗略的实现。