3

I have various sizes of rectangles, and I am trying to fit them into a larger rectangle starting from the center. Below you will find an animation I created to visually describe what needs to take place.

I have been struggling to come up with a way to model this behavior. Does anything exist that is similar to this? I just need to be pointed in the right direction.

enter image description here

The following is a very rough explanation:

Initialize

  • Start with n rectangles
  • Order by density (they are really 3d cubes bird's eye view)
  • Place first rectangle at center

Remaining rectangles (fit as many as I can) try to group highest density in the center and move outward

Dimensions = { width: 400, height: 300 }
Boundries = {
  WEST = 0,
  EAST = Dimensions.width,
  NORTH = 0,
  SOUTH = Dimensions.height
}

// each rectangle has width, height, and other information
rectArr = Array of {width:60, height:40}

root = { x:EAST/2, y:SOUTH/2 }

foreach rect in rectArr {
  // I will always traverse from the root and try to go left and right. If I cannot, I move up and try the same thing. I then move down. The problem is if there are 5 or more rows. I will be starting from the root and going up, then down, then up-up, then down. It's like I have two parallel trees.

  // Try to branch left or right
  if rect.width <= (Boundries.EAST - ('rightmost rectangle'.x + 'rightmost rectangle'.width/2)) branch-right
  if rect.width <= (('leftmost rectangle'.x + 'leftmost rectangle'.width/2) - Boundries.WEST) branch-left
  // Try to branch up or down
  if rect.height <= ((root.x + root.height/2) - Boundries.NORTH) branch-up
  if rect.height <= (Boundries.SOUTH - (root.x + root.height/2)) branch-down
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • Nice animation. Do you have some constraints on the individual rectangles? eg., there are always nine of them, or they are usually about the same size, say within a factor of some small number? – rici Feb 26 '13 at 01:46
  • I will update my question to be more descriptive. – Mr. Polywhirl Feb 26 '13 at 01:49
  • what's wrong with your solution? What was expected? Didn't you reach it? Does total area of smaller rects ≈ area of larger rect? what are other constraints here? – जलजनक Feb 26 '13 at 02:06
  • It's hard to make suggestions when you haven't told us what your constraints are, or what you're trying to optimise. Some issues I see: are you optimising for # of rectangles fitted, or density near centre? Is it required to have horizontal gaps that go from the big rectangle's end-to-end, as your solution guarantees? – congusbongus Feb 26 '13 at 02:17

1 Answers1

1

EDIT: Started writing this too early. This solution only pertains to filling the larger rectangle with as many small rectangles as is possible assuming the locations of the smaller rectangles is static.

Sounds like a dynamic programming solution will work best here; if you haven't studied algorithms, I'd advise looking into the definition of greedy algorithms, the definition of dynamic programming algorithms, examples of each kind, and where you'd use one rather than the other.

This problem is very similar to the weighted scheduling problem, but in 2 dimensions. In weighted scheduling, we're given an interval and a set of sub intervals and asked to determine the set of sub intervals whose summed weights are the largest and whose ranges don't overlap:

|--------------------------|
|{--a--}-------------------|
|----{------b-------}------|
|--------{----c----}-------|
|--------------------{-d-}-|

If we expanded this to two dimensions, the larger interval would be the x/y lengths of the bounding rectangle, the sub intervals would be the x/y lengths of the smaller rectangles, and the sub interval's weights are the areas of the smaller rectangles.

In the greedy algorithm, we would attempt to fill the bounding rectangle with as many of the biggest sub rectangles as was possible, then attempt to fit in as many of the the second biggest, then third biggest and so on until none of your rectangles fit. The problem with it is that you may end up filling in less of the bounding rectangle when using 1 of the biggest sub rectangles than when using 4 of the second biggest (think of the case where we have a a bounding square with sides size 6, the biggest sub-squares have sides size 5, and the second biggest sub-squares have sides with size 3). It looks like your initial solution may run into this same problem.

The dynamic programming solution breaks the larger problem down into overlapping subproblems, then builds up a solution based on the sub problem's outcomes. In the case of the rectangles, you want to ask the same question for every rectangle in your set: is the outcome better when I include it or when I don't include it in my solution. Based on the answer to this question, you'd add the rectangle to your solution set and remove all other rectangles it overlaps with or you'd remove only that rectangle and continue. I'd propose the following psudeo code:

compute_opt ( set of rectangles ){
  if(set.size == 0)
    return 0
  return max (area of selected rectangle i +  
              compute_opt( rectangles that don't overlap with i) ,
              compute_opt( rectangles without rectangle i included) )
}

I'm a bit rusty on memoization, so I won't go into it here. But see this princeton lecture on dynamic programming for more info on weighted scheduling. You should be able to figure out the specifics of the rectangle problem given the specifics of the interval problem.

ryanbwork
  • 2,123
  • 12
  • 12
  • Sorry, I know the greediest way is to try to fill up the most area, but I am using density as my greedy aspect and I need to start from the center. – Mr. Polywhirl Feb 26 '13 at 02:56