Supposed you've got a large amount of boxes drawn, and the user can draw a rectangular area over them.
While I'll be implementing it inside a browser, let's abstract it away and say we've got the coordinates of every point of every rectangle.
What are the most efficient data structures and algorithms here, given I want to check which boxes a) intersect b) are contained by the selection?
My current idea is to:
Sort all boxes by x
Via binsearch, check which boxes overlap x-wise with the selection area, then, for every x-wise overlapping box, check if they align y-wise as well.
or
Sort all boxes by x and y, each in separate array
Via binsearch, first find all x-overlapping boxes, then all y-overlapping boxes, then check which boxes are in both sets,
... though I'm pretty sure there's some well-known algorithm for such a problem.
I suppose by selected via some rectangle you mean either intersects some rectangle or is contained in some rectangle. If the "drawn boxes" are of fixed position, one approach which comes to mind is binary space partition. Roughly speaking, an (ideally balanced) binary space partition tree could be generated for the "drawn boxes". If the selection rectangle is positioned, the positions of its corners would be matched against the binary space partition tree, and large halfspaces could be excluded from explicit checking for intersection.
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 am working on small project that requires me to quickly find which triangles within a set of triangles is either partially or entirely contained within a given rectangular region. I am interested in optimizing for fast searches - I am not memory limited.
This is not an area I am too familiar with, so all I've been able to do thus far is to poke around on Google for standard algorithms for dealing with this problem. The closest I've gotten to so far is to use two interval trees. This is a bit clumsy, since I have to perform a test for interval overlap between the edges of each triangle and the edges of the rectangular region in both directions x and y.
Can someone point me to any resource where the 'correct' way of dealing with this problem is?
Thanks!
Edit: I forgot to mention that the rectangular regions I am currently using are parallel to the coordinate axes x and y. For the time being, I am happy with any solution that exploits this constraint. Generally, though, a solution with completely arbitrary rectangles would be great to know about.
You can use an AABBTree (AABB stands for Axis Aligned Bounding Box tree), the
idea is to enclose each triangle in its axis aligned bounding box, then build a tree that has the initial triangles as leafs, and where upper nodes have a bounding box that is the union of the bounding boxes of its children. Then when searching which triangles have a non-empty intersection with "something", you check whether the "something" has an intersection with the bounding box of a node, and go down the tree to test its children when it's the case (recursive function).
You can find efficient implementations of AABBTrees in:
CGAL: http://doc.cgal.org/latest/AABB_tree/
the GEOGRAM library that I am writing: http://alice.loria.fr/software/geogram/doc/html/classGEO_1_1MeshFacetsAABB.html
OpCode: http://www.codercorner.com/Opcode.htm
Assuming the rectangle is axis aligned, I'd do this:
Compare the bounding box of a triangle to the region. If it is inside, the triangle is inside. If there is no overlap at all, it's not. Use an interval tree for each dimension for this step if you need to check the same set of triangles with different regions.
We have checked the two simple cases in step one, so we know the region and bounding box overlap. Check if any of the points of the triangle is inside the rectangle. If so, the triangle is inside.
Check the four sides of the rectangle with the three sides of the triangle for line segment intersections
If no preprocessing of the set of triangles is allowed, there is nothing better you can do than comparing exhaustively every triangle to the window.
To solve the triangle/rectangle overlap problem easily (or just to reason about it), you can form the Minkowski sum of the two polygons, to turn the problem in a "point-in-convex-polygon" instance.
Of course, an initial axis-aligned bounding box test is welcome.
If your window is a rotated rectangle, you can "unrotate" the whole scene to make the window axis-aligned and revert to the first problem.
I'll do my best to make my case scenario simple.
1-) Let's suppose we need to stores a lot of rectangles in some kind of array/data structure. Each rectangle are of different sizes and are positioned at various parts of the screen. Rectangles can't overlap together.
2-) Then we click on the screen with the mouse at point [x,y].
Now, we need to determine if we clicked on a part of one of the rectangles. Well, that would be insane to iterate through all the rectangles to make some kind of comparisons, especially if there is a huge number of them.
What would be the fastest technique/algorithm to do it with as little steps as possible? What would be the best data structure to use in such case?
One way would be to use a quadtree to store the rectangles: The root represents the whole area that contains all rectangles, and this area is then recursively subdivided as required.
If you want to test if a certain coordinate is within one of the rectangles, you start at the root, and walk down the tree until either you find a rectangle or not.
This can be done in O(log n) time.
Let's say I have n number of equally sized and equally rotated squared boxes inside a limited area in a 2D coordinate system (floating point coordinates). The boxes should not overlap.
Now I want to find a free space for one more box. I need some tips for an algorithm to solve this. Any ideas?
There ought to be a scan line algorithm for this. You say the boxes are equally rotated, so you should be able to rotate the co-ordinate system, if necessary, so that the edges of the boxes are parallel to the x and y coordinates. I would then sort the boxes in order of y coordinate.
Now try placing a box in the lowest possible position. Read from the sorted boxes to find all the boxes low enough to interfere with your placement and create an ordered set (e.g. red-black tree or similar container class) of these boxes. Now scan along this set of boxes and see if there is a gap big enough to place a box. If not, use the original sorted list of boxes to find and remove the lowest box, so you can consider putting the new box in just above that lowest box, so it cannot interfere with this. Add more boxes from the sorted list to cover all boxes high enough to interfere with this new possible height of box. Keep track of where you have removed boxes from the list and check there to see if a gap big enough to hold a box has opened up. If not, repeat the exercise until you find a gap or run out of space at the top of the possible area.
This looks like cost N log N for the initial sort, and then a cost of at most log N per box to insert and delete boxes from the ordered set. Checking for gaps is no more expensive than this, because you only check for a gap in a location where you have just removed a box. So I think the total cost is N log N.
I've a panel of size X by Y. I want to place up to N rectangles, sized randomly, upon this panel, but I don't want any of them to overlap. I need to know the X, Y positions for these rectangles.
Algorithm, anyone?
Edit: All the N rectangles are known at the outset and can be selected in any order. Does that change the procedure?
You can model this by a set of "free" rectangles, starting with single one with coordinates of 0,0, size (x, y). Each time you need to add one more rectangle, choose one of remaining "free" rectangles, generate new rectangle (with top-left coordinate and size such that it will be fully contained), and split that rectangle as well as any other overlapping "free" rectangle, such that children express remaining free space. This will result in 0 to 4 new rectangles (0 if new rectangle was exactly the size of old free rectangle; 4 if it's in the middle and so on). Over time you will get more and more smaller and smaller free areas, so rectangles you create will be smaller as well.
Ok, not a very elaborate explanation, it's easier to show on whiteboard. But the model is one I used for finding starting location for newly cut'n pasted gui components; it's easy to keep track of available chunks of screen, and choose (for example) left or topmost such area.
Here is a decent article on 2d packing algorithms: http://www.devx.com/dotnet/Article/36005
You'll generally want some sort of algorithm using heuristics to achieve decent results. A simple (but non-optimal) solution would be the first fit algorithm.
I used this Rectangle Packing algorithm in one of my applications, available as C# source files.
The algorithm is initialized with the size of the panel, then you iterate through all rectangles and get their position. The order of the rectangles may influence the result, depending on the packer.
I would advise you use StaxMans suggestion.
Here is my 2c:
Add a whole lot of rectangles randomly (overlapping each other).
delete overlapping rectangles:
for rectangle in list of rectangles:
if rectangle not deleted:
delete all rectangles touching rectangle.
to find all the rectangles touching a particular rectangle, you can use a quad tree or inequalities based on x1,y1 x2,y2 values.
Edit: In fact, most game engines such as pygame etc include collision detection of rectangles which is a common problem.
Or maintain a list of rectangles already added and create an algorithm that figures out where to place the new rectangle based on that list. You can create a basic Rectangle class to hold the information about your rectangles.
Shouldn't be so hard to create a custom algorithm.