views:

39

answers:

1

I'm creating an application that takes a number of equally sized rectangles and positions them in a grid on the screen. I have most of the logic complete for resizing and centering a rectangle within a cell but I'm having trouble with the actual portion that defines the grid the rectangles must conform to.

Ideally, in the end I'd have a function like this (pseudo-code):


function getGridDimensions (rect surface, int numItems, float hwRatio) {
    // do something to determine grid-height and grid-width
    return gridDimensions;
}

My original stab at this involved something like this:


gridHeight = surface.width / sqrt(numItems);
gridWidth = surface.height / sqrt(numItems);

This would work nicely if my items were all perfect squares, but since they're rectangles there is a lot of unused white space within each cell.

Any thoughts or terms to Google that could point me in the right direction?

A: 

I'm a bit unclear on some of your input parameters but I'm assuming that you have Rectangle height and width, the number of rectangles and the ideal height-width ratio (ie preferred gridheight/gridwidth).

If this is the case then I'd probably start off by "normalizing" your dimensions so for the purpose of the following calculations we say a unit of width is the same as the width of a rectangle and likewise for a unit of height. If your height/width ratio in real units was k then your height/width ratio in Rectange units would be k*RectWidth/RectHeight. I'll call this K.

So now each rectangle by definition has an area of 1 so our total area is N where N is the number of items. We can then approximate our height add width to give ourselves our preferred grid aspect ratio by saying gridHeight*gridWidth = N and gridHeight/gridWidth = K

With these we get gridHeight = sqrt(KN) and gridWidth = sqrt(N/K).

If you round one of these off to a suitable whole number (I'm not sure ifwhichever is nearest a whole number rounded will give you the best result or if its whichever rounding will give the smallest percentage change in that value is best - you can always try all four if you care that much). Once you have one integer value you then calculate the other by finding the smallest integer that can multipy the other and still be greater than N to make sure you fit all rectanges in the grid).

You can then of course change your integer values back to real ones by multiply the height by rectHeight and the wdith by RectWidth.

Hopefully that all makes sense. :)

Edit for worked example:

Required final grid aspect ratio = 1024/768 (k) (assumes that 768 is width and 1024 is height - I kept wanting to put it the other way around as a standard screen resolution :) )

"Normalised" aspect ratio = (1024/768) * (300/109) = 3.6697 (K)

Grid Height therefore is sqrt(KN) = sqrt(366.97) = 19.16

Grid Width is sqrt(N/K) = 5.22

Looking at this we can see intuitively that width 5 and height 20 will be our best match. The other options might be 6 and 19. But that will waste more space (I think possibly actually minimizing the product of the width and height here migth be the best calculation but I'm not sure).

This is now our grid size in cells. This then scales up to pixel dimensions of 1500 by 2180. Scaling down to fit in 768x1024 means dividing both by 2.129 (the larger of 1500/768 and 2180/1024). So your images will scale down by 2.129 times to 141x51(ish) and your total area used will actually be 705x1020 which should give minimal whitespace.

Hopefully that makes more sense now. I'll admit, I went wrong a few times putting real values in so I totally understand why you wanted a worked example. ;-)

Chris
This seems to be what I need but I'm having a little bit of trouble following which variables you're referring to between steps. I apologize for the bother but would it be possible to go through the equations quickly with real world numbers?Total area to fill: 768x1024 —Size of images before resizing: 300x109 (eg. a 2.752 W:H ratio) —Number of cells required: 100
sevenflow
@sevenflow: Ah, for a start I misunderstood slightly the requirements which doesn't help you to understand what I did. ;-) I'll try to add in a worked case for you though...
Chris
@Chris: Thanks very much. Looking forward to it. My apologies for not explaining better!
sevenflow
@sevenflow: edit now up. I realsied as I edited that I'd also left a draft copy of parts of my post at the end of my first post too. I'm surprised it made enough sense to ask for clarification! ;-) I'm still a bit fuzzy on the best algorithm to use to decide on the rounded grid cell numbers I have to admit. You're probably best off just doing a bit of trial and error (since you might find you prefer vertical whitespace to horizontal whitespace or vice versa irrespective of the most efficient packing).
Chris
This worked and I understand the problem a lot better now. I'm having a small issue with getting the total area used to return accurately but the items are positioning themselves correctly. Thank you very much for making my first experience with Stack Overflow a pleasant one!
sevenflow
Glad to have helped. I don't get to do much maths with my job so its fun to have the occasional mathsy problems to work on. ;-)
Chris