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.
Related
Let's say I have a set of rectangles of varying widths and heights, which cannot be rotated.
I now want to fit a subset of those into a larger rectangle with a set height and width, so that the sum of the areas of the smaller rectangles is maximized.
Is there an algorithm that can help me solve this problem?
I tried looking into rectangle packing in general, but all I could find were questions about minimizing the area taken up by the rectangles.
Here is a graphical example of what I want to do:
The rectangles on the right are the aforementioned set of smaller rectangles, which I want to fit into the left one.
As I cannot possibly put all the small rectangles into the bigger one, I now have to choose an optimal subset of them, like this, for example:
Is this the best arrangement and subset of rectangles? Probably not, since there is still some space left in the bigger rectangle. In an ideal case, the would be exactly 0 space left, and the sum of the areas of the small rectangles would be equal to the area of the big rectangle. However, as this is rarely possible, I need an algorithm, that can find the best possible arrangement and subset.
I have different dimension of small rectangles (1cm x 2xm, 2cmx3cm, 4cm*6cm etc). The number of different type rectangles may vary depending on case. Each type of different rectangles may have different number of counts.
I need to create a big rectangle with all these small rectangles which these small rectangles can only be placed on the edges. no rotations. The final outer rectangle should ideally be smiliar to a square shape. X ~Y. Not all edges need to be filled up. There can be gaps in between smaller rectangles. Picture Example:
http://i.stack.imgur.com/GqI5z.png
I am trying to write a code that finds out the minimum possible area that can be formed.
I have an algorithm that loop through all possible placement to find out the minimum area possible. But that takes a long run time as number of different type rectangles and number of rectangles increase. i.e. 2 type of rectangles, each has 100 + rectangles. 8 for loops. That will be ~100^8 iterations
Any ideas on better and faster algorithm to calculate the minimum possible area? code is in python, but any algorithm concept is fine.
for rectange_1_top_count in (range(0,all_rectangles[1]["count"]+1)):
for rectange_1_bottom_count in range(0,all_rectangles[1]["count"]-rectange_1_top_count+1):
for rectange_1_left_count in (range(0,all_rectangles[1]["count"]-rectange_1_top_count-rectange_1_bottom_count+1)):
for rectange_1_right_count in ([all_rectangles[1]["count"]-rectange_1_top_count-rectange_1_bottom_count-rectange_1_left_count]):
for rectange_2_top_count in (range(0,all_rectangles[2]["count"]+1)):
for rectange_2_bottom_count in (range(0,all_rectangles[2]["count"]-rectange_2_top_count+1)):
for rectange_2_left_count in (range(0,all_rectangles[2]["count"]-rectange_2_bottom_count-rectange_2_top_count+1)):
for rectange_2_right_count in [(all_rectangles[2]["count"]-rectange_2_bottom_count-rectange_2_left_count-rectange_2_top_count)]:
area=calculate_minimum_area()
if area< minimum_area:
minimum_area=area
This looks like an NP-hard problem, so there exists no simple and efficient algorithm. It doesn't mean that there is no good heuristic that you can use, but if you have many small rectangles, you won't find the optimal solution fast.
Why is it NP-hard? Let's assume all your rectangles have height 1 and you have on rectangle of height 2, then it would make sense to look for a solution with total height 2 (basically, you try to form two horizontal lines of height-1 rectangles with the same length). To figure out if such a solution exists, you would have to form two subsets of your small rectangles, both adding up to the same total width. This is called the partition problem and it is NP-complete. Even if there may be gaps and the total widths are not required to be the same, this is still an NP-hard problem. You can reduce the partition problem to your rectangle problem by converting the elements to partition into rectangles of height 1 as outlined above.
I'll wait for the answer to the questions I posted in the comments to your question and then think about it again.
At the moment I use the slice & dice approach:
get the list of values and labels
calculate the sum of all values
calculate the ratios by dividing every value by the sum
for every list item:
draw a box with height=1 and width=ratio
draw the label on top of the box
Let me restate your question as I understood it.
You know the areas of a bunch of rectangles that you need to draw and fit into a square, and you'd like to do so with the rectangles not having extreme height/width ratios. Each rectangle represents the portion of the total value taken by a given label. The question is to figure out what the shape and positions of those rectangles should be such that they fit perfectly, and each has the required area.
You do not need a perfect answer. Only one that is better than the current, which just slices the square into vertical strips.
Here is my suggestion. Generalize to fitting rectangles in a targt rectangle. (This lets us use recursion.) Also I will assume that the labels have been sorted by area, with the largest first. (Sorting is an easy step to add.) Then figure out the placement of rectangles according to the following recursive rules:
If the first element in the list is more than 1/3 of the area, split the long side of your target rectangle into the first element, and everything else, then recursively fit everything else in the remainder.
Otherwise split your list into two, with the median of the area going into the first list. Divide your target rectangle into two, one for the first list, one for the second. Recursively fill each rectangle.
This should provide a fairly good division for your purposes with most data sets. It should be fairly fast to compute, and only the very smallest rectangle can have a ratio more extreme than 3 to 1.
I need to solve the following problem:
I have multiple rectangles of sizes: width height, width/2 height/2, width/4 height/4 , width/8 height/8 ... etc
I need to pack these rectangles in a big rectangle of size x*width y*height such that no rectangles overlap, the rectangles are distributed randomly in the packing and any rectangle should at least touch another rectangle. I tried a fairly basic greedy algorithm but it fails.
Can you give me some suggestions on how to solve the problem?
Thanks!
EDIT: You can have more than one rectangle of each size
This is not homework. I'm trying to create an effect similar to the effect on ted.com
By random I mean that there might exist more than one packing of the rectangles that satisfies the constraints. The algorithm should not produce the same packing at each run.
This sounds like a rectangle packing problem. There is a link there to an algorithm. That code packs the rectangles as tightly as possible. You said you want the rectangles to be distributed randomly, which I'm guessing means not all rectangles of one size next to each other and all rectangles spread out to fill the big rectangle. Maybe the code at the link above would be a good starting point to get some ideas.
You can use a spatial index or a quadtree to subdivide the 2d-plane. The idea is to reduce the 2d problem to a 1d-problem. Once you got the spatial index (or space-filling-curve) and you can discretize the 2d into 1d you can use the 1d to search for similarity or to sort from low to high or the reverse for example by the length. If you got this order you can then compute the index back to a 2d represenation and to pack them in most efficent way in your container. There are many ways to make a spatial index. Some of the best but difficult to make is the hilbert curve. Another one is the z-curve or morton-curve. It's different from zizag-curve because it's subdivide the plane into 4 squares (not rectangles).
EDIT: Here is a link for an Jquery-Plugin: http://www.fbtools.com/jquery/treemap/
Here with world poplulation: http://www.fbtools.com/jquery/treemap/population.html
EDIT: http://people.csail.mit.edu/konak/papers/socg_2008-circular_partitions_with_applications_to_visualization_and_embeddings.html
EDIT: http://lip.sourceforge.net/ctreemap.html
At each step you divide the surface of your new rectange by 4.
SUM(1/4n for n in [0,inf]) = 4/3**
So the best you can do is fit your rectangle in a rectangle of surface
4/3 (height*width)
(that's a lower bound)
#mloskot algorithm gives a possible solution that will be in a rectangle of surface 3/2*(height*width) : Here is an illustration:
I don't see how you can do better.
Assuming you have only one rectangle of each size, you can try to replicate the arrangement of paper sizes. Sort the rectangles by size from the biggest to the smallest, then
Take first rectangle and place it at the corner of the target plane.
Take next rectangle (assert it's smaller than the previous rectangle)
Rotate about 90 degrees
Place so
its shorter size is adjacent to the longer size of the last bigger neighbour
and its longer side is adjacent to the edge of the target plane or edge of neighbour of the same
size
Repeat 2 - 4
I realise the description might be unclear, so here is picture presenting the solution - it should help to grasp it:
This is a lot like MIP-mapping
Is there any algorithm to find a distribution of area into n sub-regions, where each sub-region might have different area.
To formally put the problem statement: Suppose you have a rectangular plot. How will you divide the region into n rectangles. The sum of area of these sub-rectangles will be equal to original rectangular plot(So there wouldn't be any overlaps between the rectangles)
And the area of each of these smaller n rectangles is given before hand.
Restriction is on width of each sub-rectangle.
This subdivision has to be displayed on may be a computer screen which is divided into pixels. So I don't want any areas any dimension to be smaller than a pixel(or maybe 10), which might be of no use to display as such.
I was looking at a rectangle packing algorithm here but this seems to be wasting space which I don't want. Does there exist any algorithm to solve this problem.
Backtracking doesn't seem to be a good solution in this case as the sub-rectangles area is only specified, not the dimensions, or is it?
Example 1:
Example 2:
The integral of a function is the area bound by the limits, the curve of the function, and the x-axis. Define one side of the rectangle as the x-axis, then find the boundaries for the others. There are plenty of numerical integration libraries around in the language of your choice.
EDIT: some difficulties in trying to illustrate in words...
Assuming, at least, that the containing rectangle has an area larger than the sum of the areas of the sub-regions; and there is no requirement of a certain order of containment:
Contain the largest sub-region first with edges on the axes.
Pick the next smaller sub-region.
Create the function (integral) to calculate the free area as seen from each axes.
With windows/limits equal to the length on the sub-region's sides (facing the axes), slide these windows along the axes away from the origin.
Create the function for finding the free space bounded by the outside arms of the cross formed by the windows as they slide along the axes. Efficiency in the use of space is found in the region where free space is minimal (differentiation).
Rotate the sub-region by 90 degrees and repeat from step 3.
Place the sub-region in the orientation and location where most efficient.
Repeat step 2. Stop when sliding windows report negative
free space for the entire domain (allocated space overlaps the placeholder made by the windows).
In theory, this will systematically try to squeeze in sub-regions. Sketch and pseudocode to follow if time permits.