在区域内保持纵横比适合N个矩形

时间:2015-01-29 23:29:46

标签: algorithm math rectangles

我有N个矩形,所有相同的尺寸 rectWidth * rectHeight 。 我有一个尺寸 areaWidth * areaHeight 的区域。 我想在区域内放置N个矩形,保持矩形的纵横比,调整矩形的大小以使它们合适。 在矩形之间,我想要一个空格的间距。

矩形的尺寸应该是什么,以使它们都适合矩形并保持纵横比?

2 个答案:

答案 0 :(得分:2)

让N个矩形 设矩形是大小(cw,ch),其中0 <0。 c≤1 让你想要的区域大小(W,H) 设s≥0是矩形之间的间距。

a的水平尺寸&gt;水平堆叠的0个矩形是acw +(a - 1)s 我们知道acw +(a - 1)s≤W。

b的垂直尺寸>垂直堆叠的0个矩形是bch +(b - 1)s 我们知道bch +(b - 1)s≤H。

然后我们有以下优化问题。

最大c
受制于 a≤(W + s)/(cw + s)
b≤(H + s)/(ch + s)
ab≥N
0&lt; c≤1
a,b> 0和整数

现在考虑以下不等式。

a≤(W + s)/(cw + s)
b≤(H + s)/(ch + s)

任何最佳解决方案必须至少使其中一个严重不平等 也就是说,以下至少一个适用于最优解(a,b,c)。

a =(W + s)/(cw + s)↔c=(W - s(a - 1))/ wa
b =(H + s)/(ch + s)↔c=(H - s(b - 1))/ wb

假设a =(W + s)/(cw + s)成立,我们假设不失一般性。
因为必须采用{1,2,...,N}中的一个值,
c必须取{W / w,(W - s)/ 2w,(W - 2s)/ 3w,......,(W - (N - 1)s)/ Nw}中的一个值。

类似的推理给出了在第二个不等式(对于b)很紧的情况下必须从中得出的值列表。

如果合并这两个值列表,则最多可以有2N个可能的值c可以采用最优解。对这些值进行排序,然后二元搜索此列表中有可行a和b的最大c。

检查c值是否可行的方法是设置

a = floor((W + s)/(cw + s))
b = floor((H + s)/(ch + s))

然后检查ab≥N。

答案 1 :(得分:1)

这个javaScript解决方案怎么样?

var areaHeight = window.innerHeight;   //set here your area height
var areaWidth = window.innerWidth;     //set here your area width
var N = 216;                           //set amount of rectangles you want to fit
var rectRatio = 9/4;                   //set rectangle ratio
var gutter = [5, 10];                  //set x and y spacing between rectangles
var cols, rows, rectHeight, rectWidth; //variables that we need to calculate

该函数假定矩形网格(画布)始终适合容器区域的高度。您向函数提供行数并计算rect大小并确定画布宽度是否大于容器宽度。如果canvas更大,我们会行++并再次调用该函数。

function rowIterator(iterator) {
   rows = iterator;
   cols = Math.ceil(N/rows);  

   rectHeight = (areaHeight - (rows-1)*gutter[1])/rows;          
   rectWidth = rectHeight*rectRatio;

   if (cols * rectWidth + (cols - 1)*gutter[0] > areaWidth) {
       rowIterator(rows + 1);
   }
}

rowIterator(1);                       //feed initial value
var size1 = [rectWidth, rectHeight];

如果您还关心找到MAX rect size并且不仅适合它,那么也应该对列进行迭代,并且应该选择更大的rect大小:

function colIterator(iterator) {
   cols = iterator;
   rows = Math.ceil(N/cols);

   rectWidth = (areaWidth - (cols - 1)*gutter[0])/cols;
   rectHeight = rectWidth/rectRatio;

   if (rows * rectHeight + (rows - 1)*gutter[1] > areaHeight) {
       colIterator(cols + 1);
   }
}
colIterator(1);
var size2 = [rectWidth, rectHeight];

两个迭代器的迭代总量大约为N,最大矩形大小为:

optimalRectSize = [Math.max(size1[0], size2[0]), Math.max(size1[1], size2[1])]
相关问题