Algorithm to fill large rectangle with smaller rectangles starting from center - algorithm

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

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.

Related

what algorithm or approach for placing rectangles without overlapp

I have a big rectangle of size 12*12. Now I have 6 rectangles already placed on the floor of that rectangle. I know the center coordinate of that pre-placed module. Now I have few another 14 rectangles to place upon that floor of that rectangle. How to do so?
here all my pre placed block those having center coordinate as say (2,5),(5,7),(9,2),(7,8),(11,9),(3,11).
Now how could I place 14 another rectangle in this floor so that it would not over lap with any preplaced block.
I would like to code in MATLAB..but what approach should I follow?
If a nice even placement is important, I suggest you look up simulated force-based graph layout. In this problem, you'll use simulated forces pushing the rectangles apart and also away from the border rectangle according to Coulomb's law. The initial configuration is randomly selected. You'll want to give the rectangles mass proportional to their area, I think. You don't have any spring forces due to edges, which makes it easier. The iteration to solve the differential equations of motion will be easy in Matlab. Or there may well be a toolkit to do it for you. Animations of these algorithms are fun.
Unfortunately with constrained problems like this, the fixed rectangles can form barriers that prevent the moving rectangles from getting to a non-overlapping solution. (Think of the case where the fixed rectangles are in a line down the middle and all the moving ones get "trapped" on one side or the other. The same thing happens in graph layout if some nodes have fixed locations.) There are various strategies for overcoming these bad cases. One is to start with no fixed objects at all, let the moving rectangles come to an equilibrium, then add the fixed ones one at a time, largest first, allowing the system regain equilibrium each time. Another, simpler one is just to start from different random initial conditions until you find one that works. There are also approaches related to simulated annealing, which is too big a topic to discuss here.
Here is a function to check overlap for two rectangles. you could loop it to check for more number of rectangles based on #Dov's idea.
For two rectangles Ri, i = 1,2, with centers (xi,yi) and half-lengths of their sides ai,bi > 0 (assuming that the sides are aligned with the coordinate axes).
Here is my implementation based on above equation:
In my code i've taken xcPosition and ycPosition as the center position of the rectangle.
Also length and breadth are the magnitude of sides of the rectangle.
function [ overLap, pivalue ] = checkOverlap( xcPosition1,ycPosition1,xcPosition2,ycPosition2,length1,breadth1,length2,breadth2 )
pix = max((xcPosition2 - xcPosition1 -(length1/2)-(length2/2)),(xcPosition1 -xcPosition2 -(length2/2)-(length1/2)));
piy = max((ycPosition2 - ycPosition1 -(breadth1/2)-(breadth2/2)),(ycPosition1 -ycPosition2 -(breadth2/2)-(breadth1/2)));
pivalue = max(pix, piy);
if (pivalue < 0)
overLap = 1; %// Overlap exists
else
overLap = 0; %// No overlap
end
end
You could also use the pivalue to know the degree of overlap or Non-overlap
The Pseudo-code for looping would be something like this:
for i = 1 : 14
for j = 1 : i-1 + 6 already placed parts
%// check for overlap using the above function here
%// place the part if there is no overlap
end
end
With such a small number, put each rectangle in a list. Each time you add a new rectangle, make sure the new one does not overlap with any of the existing ones.
This is O(n^2), so if you plan to increase to 10^3 or more rectangles you will need a better algorithm, but otherwise you're fine.
Now if your problem specifies that you might not be able to fit them all, then you will have to backtrack and keep trying different places. That is an N! problem, but if you have a lot of open space, many solutions will be possible.

Minimum number of rectangles in shape made from rectangles?

I'm not sure if there's an algorithm that can solve this.
A given number of rectangles are placed side by side horizontally from left to right to form a shape. You are given the width and height of each.
How would you determine the minimum number of rectangles needed to cover the whole shape?
i.e How would you redraw this shape using as few rectangles as possible?
I've can only think about trying to squeeze as many big rectangles as i can but that seems inefficient.
Any ideas?
Edit:
You are given a number n , and then n sizes:
2
1 3
2 5
The above would have two rectangles of sizes 1x3 and 2x5 next to each other.
I'm wondering how many rectangles would i least need to recreate that shape given rectangles cannot overlap.
Since your rectangles are well aligned, it makes the problem easier. You can simply create rectangles from the bottom up. Each time you do that, it creates new shapes to check. The good thing is, all your new shapes will also be base-aligned, and you can just repeat as necessary.
First, you want to find the minimum height rectangle. Make a rectangle that height, with the width as total width for the shape. Cut that much off the bottom of the shape.
You'll be left with multiple shapes. For each one, do the same thing.
Finding the minimum height rectangle should be O(n). Since you do that for each group, worst case is all different heights. Totals out to O(n2).
For example:
In the image, the minimum for each shape is highlighted green. The resulting rectangle is blue, to the right. The total number of rectangles needed is the total number of blue ones in the image, 7.
Note that I'm explaining this as if these were physical rectangles. In code, you can completely do away with the width, since it doesn't matter in the least unless you want to output the rectangles rather than just counting how many it takes.
You can also reduce the "make a rectangle and cut it from the shape" to simply subtracting the height from each rectangle that makes up that shape/subshape. Each contiguous section of shapes with +ve height after doing so will make up a new subshape.
If you look for an overview on algorithms for the general problem, Rectangular Decomposition of Binary Images (article by Tomas Suk, Cyril Höschl, and Jan Flusser) might be helpful. It compares different approaches: row methods, quadtree, largest inscribed block, transformation- and graph-based methods.
A juicy figure (from page 11) as an appetizer:
Figure 5: (a) The binary convolution kernel used in the experiment. (b) Its 10 blocks of GBD decomposition.

Position N circles of different radii inside a larger circle without overlapping

Given n circles with radii r1 ... rn, position them in such a way that no circles are overlapping and the bounding circle is of "small" radius.
The program takes a list [r1, r2, ... rn] as input and outputs the centers of the circles.
I ask for "small" because "minimum" radius converts it into a much more difficult problem (minimum version has already been proved to be NP hard/complete - see footnote near end of question). We don't need the minimum. If the shape made by the circles seems to be fairly circular, that is good enough.
You can assume that Rmax/Rmin < 20 if it helps.
A low priority concern - the program should be able to handle 2000+ circles. As a start, even 100-200 circles should be fine.
You might have guessed that the circles need not be packed together tightly or even touching each other.
The aim is to come up with a visually pleasing arrangement of the given circles which can fit inside a larger circle and not leave too much empty space. (like the circles in a color blindness test picture).
You can use the Python code below as a starting point (you would need numpy and matplotlib for this code - "sudo apt-get install numpy matplotlib" on linux)...
import pylab
from matplotlib.patches import Circle
from random import gauss, randint
from colorsys import hsv_to_rgb
def plotCircles(circles):
# input is list of circles
# each circle is a tuple of the form (x, y, r)
ax = pylab.figure()
bx = pylab.gca()
rs = [x[2] for x in circles]
maxr = max(rs)
minr = min(rs)
hue = lambda inc: pow(float(inc - minr)/(1.02*(maxr - minr)), 3)
for circle in circles:
circ = Circle((circle[0], circle[1]), circle[2])
color = hsv_to_rgb(hue(circle[2]), 1, 1)
circ.set_color(color)
circ.set_edgecolor(color)
bx.add_patch(circ)
pylab.axis('scaled')
pylab.show()
def positionCircles(rn):
# You need rewrite this function
# As of now, this is a dummy function
# which positions the circles randomly
maxr = int(max(rn)/2)
numc = len(rn)
scale = int(pow(numc, 0.5))
maxr = scale*maxr
circles = [(randint(-maxr, maxr), randint(-maxr, maxr), r)
for r in rn]
return circles
if __name__ == '__main__':
minrad, maxrad = (3, 5)
numCircles = 400
rn = [((maxrad-minrad)*gauss(0,1) + minrad) for x in range(numCircles)]
circles = positionCircles(rn)
plotCircles(circles)
Added info : The circle packing algorithm commonly referred to in google search results is not applicable to this problem.
The problem statement of the other "Circle packing algorithm" is thus : Given a complex K ( graphs in this context are called simplicial complexes, or complex in short) and appropriate boundary conditions, compute the radii of the corresponding circle packing for K....
It basically starts off from a graph stating which circles are touching each other (vertices of the graph denote circles, and the edges denote touch/tangential relation between circles). One has to find the circle radii and positions so as to satisfy the touching relationship denoted by the graph.
The other problem does have an interesting observation (independent of this problem) :
Circle Packing Theorem - Every circle packing has a corresponding planar graph (this is the easy/obvious part), and every planar graph has a corresponding circle packing (the not so obvious part). The graphs and packings are duals of each other and are unique.
We do not have a planar graph or tangential relationship to start from in our problem.
This paper - Robert J. Fowler, Mike Paterson, Steven L. Tanimoto: Optimal Packing and Covering in the Plane are NP-Complete - proves that the minimum version of this problem is NP-complete. However, the paper is not available online (at least not easily).
Not a solution, just a brainstorming idea: IIRC one common way to get approximate solutions to the TSP is to start with a random configuration, and then applying local operations (e.g. "swapping" two edges in the path) to try and get shorter and shorter paths. (Wikipedia link)
I think something similar would be possible here:
Start with random center positions
"Optimize" these positions, so there are no overlapping circles and so the circles are as close as possible, by increasing the distance between overlapping circles and decreasing the distance between other circles, until they're tightly packed. This could be done by some kind of energy minimization, or there might be a more efficient greedy solution.
Apply an iterative improvement operator to the center positons
Goto 2, break after a maximum number of iterations or if the last iteration didn't find any improvement
The interesting question is: what kind of "iterative improvement operator" could you use in step 3? We can assume that the positions at that stage are locally optimal, but they might be improved by rearranging a large fraction of the circles. My suggestion would be to arbitrarily choose a line through the circles. Then take all the circles "left" of the line and mirror them at some axis perpendicular to that line:
You would probably try multiple lines and pick the one that leads to the most compact solution.
The idea is, if some of the circles are already at or close to their optimal configuration, chances are good this operation won't disturb them.
Other possible operations I could think of:
Take one of the circles with the highest distance from the center (one touching the boundary circle), and randomly move it somewhere else:
Choose a set of cirlces that are close to each other (e.g. if their centers lie in an randomly chosen circle) and rotate them by a random angle.
Another option (although a bit more complex) would be to measure the area between the circles, when they're tightly packed:
Then you could pick one of the circles adjacent to the largest between-circle-area (the red area, in the image) and swap it with another circle, or move it somewhere to the boundary.
(Response to comment:) Note that each of these "improvements" is almost guaranteed to create overlaps and/or unneccessary space between circles. But in the next iteration, step 2 will move the circles so they are tightly packed and non-overlapping again. This way, I can have one step for local optimizations (without caring about global ones), and one for global optimizations (which might create locally suboptimal solutions). This is far easier than having one complex step that does both.
I have a pretty naive one pass (over the radii) solution that produces alright results, although there is definitely room for improvement. I do have some ideas in that direction but figure I might as well share what I have in case anybody else wants to hack on it too.
It looks like they intersect at the center, but they don't. I decorated the placement function with a nested loop that checks every circle against every other circle (twice) and raises an AssertionError if there is an intersection.
Also, I can get the edge close to perfect by simply reverse sorting the list but I don't think the center looks good that way. It's (pretty much the only thing ;) discussed in the comments to the code.
The idea is to only look at discrete points that a circle might live at and iterate over them using the following generator:
def base_points(radial_res, angular_res):
circle_angle = 2 * math.pi
r = 0
while 1:
theta = 0
while theta <= circle_angle:
yield (r * math.cos(theta), r * math.sin(theta))
r_ = math.sqrt(r) if r > 1 else 1
theta += angular_res/r_
r += radial_res
This just starts at the origin and traces out points along concentric circles around it. We process the radii by sorting them according to some parameters to keep the large circles near the center (beginning of list) but enough small ones near the beginning to fill in spaces. We then iterate over the radii. within the main loop, we first loop over points that we have already looked at and saved away. If none of those are suitable, we start pulling new points out of the generator and saving them (in order) until we find a suitable spot. We then place the circle and go through our list of saved points pulling out all of the ones that fall within the new circle. We then repeat. on the next radius.
I'll put some ideas I have into play and make it mo`bettah. This might serve as a good first step for a physics based idea because you get to start with no overlaps. Of course it might already be tight enough so that you wouldn't have much room.
Also, I've never played with numpy or matplotlib so I write just vanilla python. There might be something in there that will make it run much faster, I'll have to look.
Can you treat the circles as charged particles in a charged cavity and look for a stable solution? That is, circles repel one another according to proximity, but are attracted towards the origin. A few steps of simulation might get you a decent answer.
Sounds like a Circle Packing problem, here is some information:
Circle Packing Wolfram MathWorld
Circle Packing Algorithms Google Scholar
CirclePack software
http://en.wikipedia.org/wiki/Apollonian_gasket
This seems somewhat relevant to what you are trying to do, and may provide some potential constraints for you.

Partition a rectangle into near-squares of given areas

I have a set of N positive numbers, and a rectangle of dimensions X and Y that I need to partition into N smaller rectangles such that:
the surface area of each smaller rectangle is proportional to its corresponding number in the given set
all space of big rectangle is occupied and there is no leftover space between smaller rectangles
each small rectangle should be shaped as close to square as feasible
the execution time should be reasonably small
I need directions on this. Do you know of such an algorithm described on the web? Do you have any ideas (pseudo-code is fine)?
Thanks.
What you describe sounds like a treemap:
Treemaps display hierarchical (tree-structured) data as a set of nested rectangles. Each branch of the tree is given a rectangle, which is then tiled with smaller rectangles representing sub-branches. A leaf node's rectangle has an area proportional to a specified dimension on the data.
That Wikipedia page links to a page by Ben Shneiderman, which gives a nice overview and links to Java implementations:
Then while puzzling about this in the faculty lounge, I had the Aha! experience of splitting the screen into rectangles in alternating horizontal and vertical directions as you traverse down the levels. This recursive algorithm seemed attractive, but it took me a few days to convince myself that it would always work and to write a six line algorithm.
Wikipedia also to "Squarified Treemaps" by Mark Bruls, Kees Huizing and Jarke J. van Wijk (PDF) that presents one possible algorithm:
How can we tesselate a rectangle recursively into rectangles, such that their aspect-ratios (e.g. max(height/width, width/height)) approach 1 as close as possible? The number of all possible tesselations is very large. This problem falls in the category of NP-hard problems. However, for our application we do not need the optimal solution, a good solution
that can be computed in short time is required.
You do not mention any recursion in the question, so your situation might be just one level of the treemap; but since the algorithms work on one level at a time, this should be no problem.
I have been working on something similar. I'm prioritizing simplicity over getting as similar aspect ratios as possible. This should (in theory) work. Tested it on paper for some values of N between 1 and 10.
N = total number of rects to create,
Q = max(width, height) / min(width, height),
R = N / Q
If Q > N/2, split the rect in N parts along its longest side.
If Q <= N/2, split the rect in R (rounded int) parts along its shortest side.
Then split the subrects in N/R (rounded down int) parts along its shortest side.
Subtract the rounded down value from the result of the next subrects division. Repeat for all subrects or until the required number of rects are created.

Packing rectangles for compact representation

I am looking for pointers to the solution of the following problem: I have a set of rectangles, whose height is known and x-positions also and I want to pack them in the more compact form. With a little drawing (where all rectangles are of the same width, but the width may vary in real life), i would like, instead of.
-r1-
-r2--
-r3--
-r4-
-r5--
something like.
-r1- -r3--
-r2-- -r4-
-r5--
All hints will be appreciated. I am not necessarily looking for "the" best solution.
Your problem is a simpler variant, but you might get some tips reading about heuristics developed for the "binpacking" problem. There has been a lot written about this, but this page is a good start.
Topcoder had a competition to solve the 3D version of this problem. The winner discussed his approach here, it might be an interesting read for you.
Are the rectangles all of the same height? If they are, and the problem is just which row to put each rectangle in, then the problem boils down to a series of constraints over all pairs of rectangles (X,Y) of the form "rectangle X cannot be in the same row as rectangle Y" when rectangle X overlaps in the x-direction with rectangle Y.
A 'greedy' algorithm for this sorts the rectangles from left to right, then assigns each rectangle in turn to the lowest-numbered row in which it fits. Because the rectangles are being processed from left to right, one only needs to worry about whether the left hand edge of the current rectangle will overlap any other rectangles, which simplifies the overlap detection algorithm somewhat.
I can't prove that this is gives the optimal solution, but on the other hand can't think of any counterexamples offhand either. Anyone?
Something like this?
Sort your collection of rectangles by x-position
write a method that checks which rectangles are present on a certain interval of the x-axis
Collection<Rectangle> overlaps (int startx, int endx, Collection<Rectangle> rects){
...
}
loop over the collection of rectangles
Collection<Rectangle> toDraw;
Collection<Rectangle> drawn;
foreach (Rectangle r in toDraw){
Collection<Rectangle> overlapping = overlaps (r.x, r.x+r.width, drawn);
int y = 0;
foreach(Rectangle overlapRect in overlapping){
y += overlapRect.height;
}
drawRectangle(y, Rectangle);
drawn.add(r);
}
Put a tetris-like game into you website. Generate the blocks that fall and the size of the play area based on your paramters. Award points to players based on the compactness (less free space = more points) of their design. Get your website visitors to perform the work for you.
I had worked on a problem like this before. The most intuitive picture is probably one where the large rectangles are on the bottom, and the smaller ones are on top, kinda like putting them all in a container and shaking it so the heavy ones fall to the bottom. So to accomplish this, first sort your array in order of decreasing area (or width) -- we will process the large items first and build the picture ground up.
Now the problem is to assign y-coordinates to a set of rectangles whose x-coordinates are given, if I understand you correctly.
Iterate over your array of rectangles. For each rectangle, initialize the rectangle's y-coordinate to 0. Then loop by increasing this rectangle's y-coordinate until it does not intersect with any of the previously placed rectangles (you need to keep track of which rectangles have been previously placed). Commit to the y-coordinate you just found, and continue on to process the next rectangle.

Resources