views:

73

answers:

4

I have N squares. I have a Rectangular box. I want all the squares to fit in the box. I want the squares to be as large as possible.

How do I calculate the largest size for the squares such that they all fit in the box?

This is for thumbnails in a thumbnail gallery.

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;
 }

This code currently works OK. The idea behind it is to take the smallest dimension of the rectangular container, pretend the container is a square of that dimension, and then assume we have an equal number of rows and columns, just enough to fit iItems squares inside.

This function works great if the container is mostly squarish. If you have a long rectangle, though, the thumbnails come out smaller than they could be. For instance, if my rectangle is 100 x 300, and I have three thumbnails, it should return 100, but instead returns 33.

A: 

you want something more like

n = number of thumbnails x = one side of a rect y = the other side l = length of a side of a thumbnail

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

Keith Nicholas
Just tried a quick experiment: 900 x 900 rectangle with 8 items. Length = 318. 3 rows and 3 cols means you are at 954 pixels wide, which is bigger than the rectangle.
Jake
ahhh, yes, just need to scale it to the min fitting scale as the poster below does
Keith Nicholas
+1  A: 

Probably not optimal (if it works which I haven't tried), but I think better than you current approach :

w: width of rectangle

h: height of rectangle

n: number of images

a = w*h : area of the rectangle.

ia = a/n max area of an image in the ideal case.

il = sqrt(ia) max length of an image in the ideal case.

nw = round_up(w/il): number of images you need to stack on top of each other.

nh = round_up(h/il): number of images you need to stack next to each other.

l = min(w/nw, w/nh) : length of the images to use.

Carsten
A quick run through in my spreadsheet and I believe we have a winner! Give me one moment to put this in my program and test it out.
Jake
A: 

Here is my final code based off of unknown (google)'s reply: For the guy who wanted to know what language my first post is in, this is 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
Jake
A: 

This should work. It is solved with an algorithm rather than an equation. The algorithm is as follows:

  • Span the entire short side of the rectangles with all of the squares
  • Decrease the number of squares in this span (as a result, increasing the size) until the depth of the squares exceeds the long side of the rectangle
  • Stop when the span reaches 1, because this is as good as we can get.

Here is the code, written in 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);
}
Stephen Delano