I have been struggling with finding a convenient solution for the following problem:
Suppose we have a wall of a given size and 4 types of tiles of sizes 4 x 2, 2 x 2, 2 x 1, 1 x 1. There are certain rectangular regions inside the perimeter of the wall which can not be tiled (i.e. holes). There is also a special type of tile which has a variable dimension A x B with A < 1. This is used to pad the tiling to the margin of the rectangle, if needed.
Find a tiling of the wall which respects the following constraints:
Tiles of the same size can not be placed one below the other, with the same alignment (i.e. tiles appearing on a row below have to be shifted such that there is no gap which looks like a cross between adjoining tiles of the same size)
A minimum number of tiles is used
Tiles which exceed the boundaries of the rectangle will be trimmed to the margin; the incomplete tile thus produced will be broken in smaller tiles; this could possibly involve the use of a special tile which should always sit next to the margin of the rectangle or the margin of a hole, wherever the situation might arise
Here is what I've tried so far:
I've looked into algorithms for solving this using domino tiling but most don't seem to care that the tiling process can not produce gaps which look like a cross where tiles meet. Also, to me the problem seems a bit different as there are more types of tiles and it also seems that the rectangle does not have to be exactly filled (it is possible for small spaces to remain near the margins which will be filled using special tiles)
I've tried to generate all possible tilings using a branch and bound technique with state node pruning so that only those states where tiles which do not break the constraints are added will be explored, but this is definitely not scalable.
I've also looked into packing algorithms but to my knowledge, this might lead to a certain tiling where there are small untiled spaces which can remain inside the premises of the wall.
It might be possible that I've overlooked something, or not had enough insight while exploring the above techniques.
With all these being said, do you guys have any hints or suggestions on a way to approach this which yields results?
This is an example of a tiling which respects constraints 1 and 3, but is not optimal
Do you need the optimal tiling, or are you willing to settle for "pretty good"? Finding the optimal solution is likely exceedingly hard. Intuitively, I would suggest the following heuristic:
1. Pretend there are no holes in the wall, tile with large tiles.
2. Remove all tiles which intersect with holes.
3. current_size = largest
4. For each empty space: tile as much as possible with current_size
5. current_size = the size just below current_size
6. return to 4
Related
What I am asking here is an algorithm question. I'm not asking for specifics of how to do it in the programming language I'm working in or with the framework and libraries I'm currently using. I want to know how to do this in principle.
As a hobby, I am working on an open source virtual reality remake of the 1992 first-person shooter game Wolfenstein 3D. My program will support classic mods and map packs for WOLF3D made in the original format from the 90s. This means that my program will not know in advance what the maps are going to be. They are loaded in at runtime from user provided files.
A Wolfenstein 3D map is a 2D square grid of normally 64x64 tiles. let's assume I have a 2D array of bools which return true if a particular tile can be traversed by the player and false if the tile will never be traversable no matter what happens in the game.
I want to generate rectangular collision objects for a modern game engine which will prevent collisions into non traversable tiles on the map. Right now, I have a small collision object on each surface of each wall tile with a traversible tile next to it and that is very inefficient because it makes way more collision objects than necessary. What I should have instead is a smaller number of large rectangles which fill all of the squares on the grid where that 2D array I mentioned has a false value to indicate non-traversible.
When I search for any algorithms or research that might have been done for problems similar to this, I find lots of information about rectangle packing for the purposes of making texture atlases for games, which packs rectangles into a square, but I haven't found anything that tries to pack the smallest number of rectangles into an arbitrary set of selected / marked square tiles.
The naive approach which occurs to me is to first make 64 rectangles representing 64 rows and then chop out whatever squares are traversible. but I suspect that there's got to be an algorithm which can do better, meaning that it can fill the same spaces with a smaller number of rectangles. Maybe something that starts with my naive approach and then checks each rectangle for adjacent rectangles which it could merge with? But I'm not sure how far to take that approach or if it will even truly reduce the number of rectangles.
The result doesn't have to be perfect. I am just fishing here to see if anyone has any magic tricks that could take me even a little bit beyond the naive approach.
Has anyone done this before? What is it called? Just knowing what some of the vocabulary words I would need to even talk about this are would help. Thanks!
(later edit)
Here is some sample input as comma-separated values. The 1s represent the area that must be filled with the rectangles while the 0s represent the area that should not be filled with the rectangles.
I expect that the result would be a list of sets of 4 integers where each set represents a rectangle like this:
First integer would be the x coordinate of the left/western edge of the rectangle.
Second integer would be the y coordinate of the top/northern edge of the rectangle.
Third integer would be the width of the rectangle.
Fourth integer would be the depth of the rectangle.
My program is in C# but I'm sure I can translate anything in a normal mainstream general purpose programming language or psuedocode.
Mark all tiles as not visited
For each tile:
skip if the tile is not a top-left corner or was visited before
# now, the tile is a top-left corner
expand right until top-right corner is found
expand down
save the rectangle
mark all tiles in the rectangle as visited
However simplistic it looks, it will likely generate minimal number of rectangles - simply because we need at least one rectangle per pair of top corners.
For faster downward expansion, it makes sense to precompute a table holding sum of all element top and left from the tile (aka integral image).
For non-overlapping rectangles, worst case complexity for an n x n "image" should not exceed O(n^3). If rectangles can overlap (would result in smaller number of them), integral image optimization is not applicable and the worst case will be O(n^4).
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.
I'm having the requirement, to insert a specific amount of rectangles (which have a defined width but a random height) into another rectangle (which has a defined height and the same defined width as the rectangles to insert). The goal here is, that those inserted rectangles should fill-out the target rectangle as much as possible.
For instance:
I don't need to get as much rectangles as possible into the black, the goal is to fillout the black rect as much as possible, best case, entirely.
In reality, there are many "black" rectangles and thousands of "reds", I'm looking for an effective algorithm to calculate. I have to implement this in ECMA-/Javascript so it's not really the fastest of all platforms.
I looked into some algos like Richard E. Korf's "Optimal Rectangle Packing" or "Bin packings problems", but I couldn't really translate those for this specific problem.
Can somebody recommend me a method/algorithm ?
Because your red and black triangles both have a defined width, you can reduce the problem to a number line, so to speak. Basically, if you ever flipped a red one on its side, you'd most likely end up with wasted space - much more wasted space than putting it in the 'normal fitting' way.
So with this in mind, you can reduce the problem exactly to the traditional knapsack problem where the capacity is the height of the black rectangle and the 'weight' of the red triangles are their height. The width can be entirely abstracted out of the problem.
Another advantage (as pointed out by xvatar) is that the value density of the candidates are all equal. That is to say that you don't have the "brick-ring" issue the traditional knapsack problem has. Given the choice between bricks and rings to fill your knapsack with, the rings are obvious candidates. In this case, they're all the same so there are no obvious candidates.
It would seem the big blocks are easy candidates, but this greedy approach doesn't fly. Consider the scenario where there are 5 units of space left, and we have bricks of 4, 3 and 2. If we go with the greedy solution, we add the 4, leaving 1 open space. If we would instead have gone with 3 and 2, we would not have the 1 open space remaining.
It also stands to note that once you have identified what rectangles go in, it doesn't matter what order they go in.
Further reading: http://en.wikipedia.org/wiki/Knapsack_problem
What is the most efficient way to randomly fill a space with as many non-overlapping shapes? In my specific case, I'm filling a circle with circles. I'm randomly placing circles until either a certain percentage of the outer circle is filled OR a certain number of placements have failed (i.e. were placed in a position that overlapped an existing circle). This is pretty slow, and often leaves empty spaces unless I allow a huge number of failures.
So, is there some other type of filling algorithm I can use to quickly fill as much space as possible, but still look random?
Issue you are running into
You are running into the Coupon collector's problem because you are using a technique of Rejection sampling.
You are also making strong assumptions about what a "random filling" is. Your algorithm will leave large gaps between circles; is this what you mean by "random"? Nevertheless it is a perfectly valid definition, and I approve of it.
Solution
To adapt your current "random filling" to avoid the rejection sampling coupon-collector's issue, merely divide the space you are filling into a grid. For example if your circles are of radius 1, divide the larger circle into a grid of 1/sqrt(2)-width blocks. When it becomes "impossible" to fill a gridbox, ignore that gridbox when you pick new points. Problem solved!
Possible dangers
You have to be careful how you code this however! Possible dangers:
If you do something like if (random point in invalid grid){ generateAnotherPoint() } then you ignore the benefit / core idea of this optimization.
If you do something like pickARandomValidGridbox() then you will slightly reduce the probability of making circles near the edge of the larger circle (though this may be fine if you're doing this for a graphics art project and not for a scientific or mathematical project); however if you make the grid size 1/sqrt(2) times the radius of the circle, you will not run into this problem because it will be impossible to draw blocks at the edge of the large circle, and thus you can ignore all gridboxes at the edge.
Implementation
Thus the generalization of your method to avoid the coupon-collector's problem is as follows:
Inputs: large circle coordinates/radius(R), small circle radius(r)
Output: set of coordinates of all the small circles
Algorithm:
divide your LargeCircle into a grid of r/sqrt(2)
ValidBoxes = {set of all gridboxes that lie entirely within LargeCircle}
SmallCircles = {empty set}
until ValidBoxes is empty:
pick a random gridbox Box from ValidBoxes
pick a random point inside Box to be center of small circle C
check neighboring gridboxes for other circles which may overlap*
if there is no overlap:
add C to SmallCircles
remove the box from ValidBoxes # possible because grid is small
else if there is an overlap:
increase the Box.failcount
if Box.failcount > MAX_PERGRIDBOX_FAIL_COUNT:
remove the box from ValidBoxes
return SmallCircles
(*) This step is also an important optimization, which I can only assume you do not already have. Without it, your doesThisCircleOverlapAnother(...) function is incredibly inefficient at O(N) per query, which will make filling in circles nearly impossible for large ratios R>>r.
This is the exact generalization of your algorithm to avoid the slowness, while still retaining the elegant randomness of it.
Generalization to larger irregular features
edit: Since you've commented that this is for a game and you are interested in irregular shapes, you can generalize this as follows. For any small irregular shape, enclose it in a circle that represent how far you want it to be from things. Your grid can be the size of the smallest terrain feature. Larger features can encompass 1x2 or 2x2 or 3x2 or 3x3 etc. contiguous blocks. Note that many games with features that span large distances (mountains) and small distances (torches) often require grids which are recursively split (i.e. some blocks are split into further 2x2 or 2x2x2 subblocks), generating a tree structure. This structure with extensive bookkeeping will allow you to randomly place the contiguous blocks, however it requires a lot of coding. What you can do however is use the circle-grid algorithm to place the larger features first (when there's lot of space to work with on the map and you can just check adjacent gridboxes for a collection without running into the coupon-collector's problem), then place the smaller features. If you can place your features in this order, this requires almost no extra coding besides checking neighboring gridboxes for collisions when you place a 1x2/3x3/etc. group.
One way to do this that produces interesting looking results is
create an empty NxM grid
create an empty has-open-neighbors set
for i = 1 to NumberOfRegions
pick a random point in the grid
assign that grid point a (terrain) type
add the point to the has-open-neighbors set
while has-open-neighbors is not empty
foreach point in has-open-neighbors
get neighbor-points as the immediate neighbors of point
that don't have an assigned terrain type in the grid
if none
remove point from has-open-neighbors
else
pick a random neighbor-point from neighbor-points
assign its grid location the same (terrain) type as point
add neighbor-point to the has-open-neighbors set
When done, has-open-neighbors will be empty and the grid will have been populated with at most NumberOfRegions regions (some regions with the same terrain type may be adjacent and so will combine to form a single region).
Sample output using this algorithm with 30 points, 14 terrain types, and a 200x200 pixel world:
Edit: tried to clarify the algorithm.
How about using a 2-step process:
Choose a bunch of n points randomly -- these will become the centres of the circles.
Determine the radii of these circles so that they do not overlap.
For step 2, for each circle centre you need to know the distance to its nearest neighbour. (This can be computed for all points in O(n^2) time using brute force, although it may be that faster algorithms exist for points in the plane.) Then simply divide that distance by 2 to get a safe radius. (You can also shrink it further, either by a fixed amount or by an amount proportional to the radius, to ensure that no circles will be touching.)
To see that this works, consider any point p and its nearest neighbour q, which is some distance d from p. If p is also q's nearest neighbour, then both points will get circles with radius d/2, which will therefore be touching; OTOH, if q has a different nearest neighbour, it must be at distance d' < d, so the circle centred at q will be even smaller. So either way, the 2 circles will not overlap.
My idea would be to start out with a compact grid layout. Then take each circle and perturb it in some random direction. The distance in which you perturb it can also be chosen at random (just make sure that the distance doesn't make it overlap another circle).
This is just an idea and I'm sure there are a number of ways you could modify it and improve upon it.
I am looking for an algorithm as follows:
Given a set of possibly overlapping rectangles (All of which are "not rotated", can be uniformly represented as (left,top,right,bottom) tuplets, etc...), it returns a minimal set of (non-rotated) non-overlapping rectangles, that occupy the same area.
It seems simple enough at first glance, but prooves to be tricky (at least to be done efficiently).
Are there some known methods for this/ideas/pointers?
Methods for not necessarily minimal, but heuristicly small, sets, are interesting as well, so are methods that produce any valid output set at all.
Something based on a line-sweep algorithm would work, I think:
Sort all of your rectangles' min and max x coordinates into an array, as "start-rectangle" and "end-rectangle" events
Step through the array, adding each new rectangle encountered (start-event) into a current set
Simultaneously, maintain a set of "non-overlapping rectangles" that will be your output set
Any time you encounter a new rectangle you can check whether it's completely contained already in the current / output set (simple comparisons of y-coordinates will suffice)
If it isn't, add a new rectangle to your output set, with y-coordinates set to the part of the new rectangle that isn't already covered.
Any time you hit a rectangle end-event, stop any rectangles in your output set that aren't covering anything anymore.
I'm not completely sure this covers everything, but I think with some tweaking it should get the job done. Or at least give you some ideas... :)
So, if I were trying to do this, the first thing I'd do is come up with a unified grid space. Find all unique x and y coordinates, and create a mapping to an index space. So if you have x values { -1, 1.5, 3.1 } then map those to { 0, 1, 2 }, and likewise for y. Then every rectangle can be exactly represented with these packed integer coordinates.
Then I'd allocate a bitvector or something that covers the entire grid, and rasterize your rectangles in the grid. The nice thing about having a grid is that it's really easy to work with, and by limiting it to unique x and y coordinates it's minimal and exact.
One way to come up with a pretty quick solution is just dump every 'pixel' of your grid.. run them back through your mapping, and you're done. If you're looking for a more optimal number of rectangles, then you've got some sort of search problem on your hands.
Let's look at 4 neighboring pixels, a little 2x2 square. When I write algorithms like these, typically I think in terms of verts, edges, and faces. So, these are the faces around a vert. If 3 of them are on and 1 is off, then you've got a concave corner. This is the only invalid case. For example, if I don't have any concave corners, I just grab the extents and dump the whole thing as a single rectangle. For each concave corner, you need to decide whether to split horizontally, vertically, or both. I think of the splitting as marking edges not to cross when finding extents. You could also do it as coloring into sets, whatever is easier for you.
The concave corners and their split directions are your search space.. you can use whatever optimization algorithm you'd like. Branch/bound might work well. I bet you could find a simple heuristic that performs well (for example, if there's another concave corner directly across from the one you're considering, always split in that direction. Otherwise, split in the shorter direction). You could just go greedy. Or you could just split every concave vert in both directions, which would generally give you fewer rectangles than outputting every 'pixel' as a rect, and would be pretty simple.
Reading over this I realize that there may be areas that are unclear. Let me know if you want me to clarify anything.