6

我有N个正方形。我有一个长方形盒子。我希望所有的方块都装在盒子里。我希望正方形尽可能大。

如何计算正方形的最大尺寸以使它们都适合盒子?

这适用于缩略图库中的缩略图。

int function thumbnailSize(
    iItems, // The number of items to fit.
    iWidth, // The width of the container.
    iHeight, // The height of the container.
    iMin // The smallest an item can be.
)
{
    // if there are no items we don't care how big they are!    
    if (iItems = 0) return 0;

    // Max size is whichever dimension is smaller, height or width.
    iDimension = (iWidth min iHeight);

    // Add .49 so that we always round up, even if the square root
    // is something like 1.2.  If the square root is whole (1, 4, etc..)
    // then it won't round up.
    iSquare = (round(sqrt(iItems) + 0.49));

    // If we arrange our items in a square pattern we have the same
    // number of rows and columns, so we can just divide by the number
    // iSquare, because iSquare = iRows = iColumns.
    iSize = (iDimension / iSquare);

    // Don't use a size smaller than the minimum.
    iSize = (iSize max iMin);

    return iSize;
 }

此代码当前工作正常。其背后的想法是取矩形容器的最小尺寸,假设容器是该尺寸的正方形,然后假设我们有相同数量的行和列,刚好足以容纳 iItems 正方形。

如果容器大多是方形的,这个函数就很好用。但是,如果您有一个长矩形,则缩略图会比实际显示的要小。例如,如果我的矩形是 100 x 300,并且我有三个缩略图,它应该返回 100,但返回 33。

4

8 回答 8

7

可能不是最优的(如果我没有尝试过的话),但我认为比你目前的方法更好:

w:矩形的宽度

h:矩形的高度

n:图像数量

a = w*h :矩形的面积。

ia = 理想情况下图像的 a/n 最大面积。

il = sqrt(ia) 理想情况下图像的最大长度。

nw = round_up(w/il):需要堆叠的图像数量。

nh = round_up(h/il):需要堆叠在一起的图像数量。

l = min(w/nw, w/nh) : 要使用的图像的长度。

于 2009-10-16T00:00:10.663 回答
2

https://math.stackexchange.com/a/466248上的解决方案完美运行。

未优化的 javascript 实现:

var getMaxSizeOfSquaresInRect = function(n,w,h) 
{
    var sw, sh;
    var pw = Math.ceil(Math.sqrt(n*w/h));
    if (Math.floor(pw*h/w)*pw < n) sw = h/Math.ceil(pw*h/w);
    else sw = w/pw;
    var ph = Math.ceil(Math.sqrt(n*h/w));
    if (Math.floor(ph*w/h)*ph < n) sh = w/Math.ceil(w*ph/h);
    else sh = h/ph;
    return Math.max(sw,sh);
}
于 2017-11-16T19:32:17.587 回答
2

我一直在寻找类似的解决方案,但我必须在容器中放置矩形而不是正方形。由于正方形也是矩形,我的解决方案也回答了这个问题。

我将Neptilomckeed的答案结合到fitToContainer() 函数中。给它适合的矩形数量ncontainerWidthandcontainerHeight和原始的itemWidthand itemHeight。如果项目没有原始宽度和高度,请使用itemWidthitemHeight指定项目的所需比例。

例如,fitToContainer(10, 1920, 1080, 16, 9)结果为{nrows: 4, ncols: 3, itemWidth: 480, itemHeight: 270}4 列和 3 行,大小为 480 x 270(像素,或任何单位)。

为了在 1920x1080 的相同示例区域中放置 10 个正方形,您可以调用fitToContainer(10, 1920, 1080, 1, 1)导致{nrows: 2, ncols: 5, itemWidth: 384, itemHeight: 384}.

function fitToContainer(n, containerWidth, containerHeight, itemWidth, itemHeight) {
    // We're not necessarily dealing with squares but rectangles (itemWidth x itemHeight),
    // temporarily compensate the containerWidth to handle as rectangles
    containerWidth = containerWidth * itemHeight / itemWidth;
    // Compute number of rows and columns, and cell size
    var ratio = containerWidth / containerHeight;
    var ncols_float = Math.sqrt(n * ratio);
    var nrows_float = n / ncols_float;

    // Find best option filling the whole height
    var nrows1 = Math.ceil(nrows_float);
    var ncols1 = Math.ceil(n / nrows1);
    while (nrows1 * ratio < ncols1) {
        nrows1++;
        ncols1 = Math.ceil(n / nrows1);
    }
    var cell_size1 = containerHeight / nrows1;

    // Find best option filling the whole width
    var ncols2 = Math.ceil(ncols_float);
    var nrows2 = Math.ceil(n / ncols2);
    while (ncols2 < nrows2 * ratio) {
        ncols2++;
        nrows2 = Math.ceil(n / ncols2);
    }
    var cell_size2 = containerWidth / ncols2;

    // Find the best values
    var nrows, ncols, cell_size;
    if (cell_size1 < cell_size2) {
        nrows = nrows2;
        ncols = ncols2;
        cell_size = cell_size2;
    } else {
        nrows = nrows1;
        ncols = ncols1;
        cell_size = cell_size1;
    }

    // Undo compensation on width, to make squares into desired ratio
    itemWidth = cell_size * itemWidth / itemHeight;
    itemHeight = cell_size;
    return { nrows: nrows, ncols: ncols, itemWidth: itemWidth, itemHeight: itemHeight }
}

JavaScript 实现形式 mckeed 给了我比我找到的其他答案更好的结果。首先将矩形拉伸为正方形的想法来自 Neptilo。

于 2019-11-06T16:34:32.427 回答
0

你想要更像的东西

n = 缩略图数量 x = 矩形的一侧 y = 另一侧 l = 缩略图一侧的长度

l = sqrt( (x * y) / n )

于 2009-10-15T23:44:09.557 回答
0

这是我基于未知(谷歌)回复的最终代码:对于想知道我的第一篇文章是什么语言的人,这是 VisualDataflex:

Function ResizeThumbnails Integer iItems Integer iWidth Integer iHeight Returns Integer
    Integer iArea iIdealArea iIdealSize iRows iCols iSize  
    // If there are no items we don't care how big the thumbnails are!
    If (iItems = 0) Procedure_Return
    // Area of the container.
    Move (iWidth * iHeight) to iArea
    // Max area of an image in the ideal case (1 image).
    Move (iArea / iItems) to iIdealArea
    // Max size of an image in the ideal case.
    Move (sqrt(iIdealArea)) to iIdealSize
    // Number of rows.
    Move (round((iHeight / iIdealSize) + 0.50)) to iRows
    // Number of cols.
    Move (round((iWidth / iIdealSize) + 0.50)) to iCols
    // Optimal size of an image.
    Move ((iWidth / iCols) min (iHeight / iRows)) to iSize
    // Check to make sure it is at least the minimum.
    Move (iSize max iMinSize) to iSize
    // Return the size
    Function_Return iSize
End_Function
于 2009-10-16T01:01:29.637 回答
0

这应该有效。它是用算法而不是方程来解决的。算法如下:

  • 用所有正方形跨越矩形的整个短边
  • 减少此跨度中的正方形数量(结果,增加大小),直到正方形的深度超过矩形的长边
  • 当跨度达到 1 时停止,因为这是我们能得到的最好的。

这是用 JavaScript 编写的代码:

function thumbnailSize(items, width, height, min) {

  var minSide = Math.min(width, height),
      maxSide = Math.max(width, height);

  // lets start by spanning the short side of the rectange
  // size: the size of the squares
  // span: the number of squares spanning the short side of the rectangle
  // stack: the number of rows of squares filling the rectangle
  // depth: the total depth of stack of squares
  var size = 0;
  for (var span = items, span > 0, span--) {
    var newSize = minSide / span;
    var stack = Math.ceil(items / span);
    var depth = stack * newSize; 
    if (depth < maxSide)
      size = newSize;
    else 
      break;
  }
  return Math.max(size, min);
}
于 2009-10-16T16:05:37.887 回答
0

在Objective C中......包含矩形中给定项目数的正方形边的长度。

int count = 8;    // number of items in containing rectangle
int width = 90;   // width of containing rectangle
int height = 50;  // width of container
float sideLength = 0; //side length to use.


float containerArea = width * height;
float maxArea = containerArea/count;
float maxSideLength = sqrtf(maxArea);  
float rows = ceilf(height/maxSideLength);   //round up
float columns = ceilf(width/maxSideLength); //round up

float minSideLength = MIN((width/columns), (height/rows));
float maxSideLength = MAX((width/columns), (height/rows));

// Use max side length unless this causes overlap 
if (((rows * maxSideLength) > height) && (((rows-1) * columns) < count) ||
    (((columns * maxSideLength) > width) && (((columns-1) * rows) < count))) {
    sideLength = minSideLength;
}
else {
    sideLength = maxSideLength;
}
于 2012-04-14T22:50:17.617 回答
0

我的 JavaScript 实现:

var a = Math.floor(Math.sqrt(w * h / n));
return Math.floor(Math.min(w / Math.ceil(w / a), h / Math.ceil(h / a)));

w矩形的宽度是哪里,h高度是哪里,是n你想挤进去的正方形的数量。

于 2016-06-02T16:10:19.833 回答