how to check a collection of rectangles for holes and intersctions? - java

I am searching for a way to check a collection (Java TreeSet) of rectangles - implemented by a "comparable" Java class using google guavas Range for x and y range - for intersections and holes.
i know that an option could be to use kd-trees, but I have no idea how to build such an kd-tree (for rectangles it should be 4d, shouldn't it?) and how to get the problem solved (intersection, holes).
the sorting prioritizes the x-axis over y-axis.
EDIT: (try to restate the problem): the use case is to create arbitrary tables (consisting of 2 or 3 blocks of rectangles "header","pre column","data"). i have to guarantee that there are no intersections and holes (i.e. provided by invalid html or other sources of table data) in each block (besides this the blocks must fit together).
Currently (just got an idea) i try to save in a 2d-array which positions (x,y) are occupied. at the end all position must be occupied exactly once.

There are quite a few of approaches to solving this type of a problem, each with different pros and cons. Here are some of them:
Rectangle Pair Intersection + Area Sum
Look at every pair of rectangles - if the two rectangles intersect, there is an overlap. Add up the rectangle areas and check whether the sum matches the canvas area - if the areas don't match, there is a gap.
Painting
This is the approach you mentioned: create a 2D array that has the dimensions of your canvas. Then, iterate over rectangles and "paint" them into the array.
One optimization to this approach is coordinate compression. Let's say that you have rectangles [(10,20), (15,25)] and [(7,3), (15, 25)]. You can look at the distinct x-coordinates (7, 10, 15) and remap them to (0, 1, 2), and the distinct y-coordinates (3, 20, 25) and remap them to (0, 1, 2). Then, you are left with rectangles [(1, 1), (2, 2)] and [(0,0), (2,2)], so you only need a 3x3 array for the painting, instead of a 26x26 array.
Sweep Line Algorithm
Sweep a line from left to right, stopping at 'interesting' points, and keeping track of which areas are occupied.
2D Range Trees
A data structure that can efficiently perform queries over rectangle ranges.
Which One to Pick?
It depends on the number of rectangles you have, how they are distributed in the area, how fast your algorithm must be, how much complexity you are willing to take on, etc. The first two algorithms that I mentioned are much simpler than the latter two, so I'd recommend starting there.
More Info
If you want learn more about these algorithms, try searching for "rectangle union" online. The most efficient solution is the sweep line algorithm.
Here are a couple of references on the sweep line algorithm:
What is an Efficient algorithm to find Area of Overlapping Rectangles
http://compgeom.cs.uiuc.edu/~jeffe/open/klee.html
J. L. Bentley, Algorithms for Klee's rectangle problems. Unpublished notes, Computer Science Department, Carnegie Mellon University, 1977
Reference 3. is usually given as the original source of the line sweep algorithm for rectangle union, but I have to admit that I didn't actually find the paper online, perhaps because it is "Unpublished"...

Related

Simple and fast collision algorithm in java for non-axis aligned boxes

I'm making a program that needs to detect the collision between 2 non-axis aligned boxes. My program only needs an indication if 2 non-axis aligned boxes are colliding. I would like to have the most simple and efficient algorithm possible.
Here I visualized the problem.
So as you can see squares 1,2 and 3 would return true because they collided with the green squares.
4 would return false because it isn't colliding.
I do have all the boxes of both colors in separate array lists.
Does anybody know a library or algorithm for this problem? Thanks in advance.
Check out the Area class in the java.awt.geom package.
http://docs.oracle.com/javase/6/docs/api/java/awt/geom/Area.html
I don't know how "easy" your game really is, how many shapes you'd have to check for (I'm thinking efficiency here), but if you have your different color shapes in different lists, a kind of brute force iteration may work for you. Not a clue if it would be efficient enough for you. I use box2D to tell me the collisions, but sounds like that may be overkill for you.
The brute force method I'm thinking of would be to utilize libgdx's Intersector class (check out the API, it has lots of methods). Iterate through your rectangles comparing to the others. Something like IntersectRectangles() gives you a boolean if two rectangles overlap (ie: collide).
This may be too inefficient/hacky, and a physics library may be too much. So one of the other answers provided may be the sweet spot.
A commonly-used approach involves quadtrees. There's a good write-up and tutorial here, which explains how to use quadtrees to perform collision detection in 2D space.
The general idea is that your game area will keep being partitioned by four as your add objects. Each partition is called a node and each node will maintain a reference to objects that exist in the corresponding partition. Objects are placed into nodes based on where they are in the 2D space. If a node does not fit cleanly into a partition, it is inserted into the parent node. Using this method, you don't have to perform an expensive check against every other object in your 2D space, because you can be sure that objects in different nodes (at the same level; i.e., sibling nodes) will not collide. So you only have to perform your collision detection on a small subset of objects.
Note that this just tells you which objects are occupying a certain area; it's a more efficient way to hone in on objects that are likely to be colliding. After that you have to check if the objects are actually colliding. There is another write-up here that goes over various techniques to accomplish this.
There are two algorithms/data-structures you need to consider for this problem:
A spatial data-structure to store your rotated quads, to efficiently determine which pairs of quads need to be tested against each other. Other answers have already addressed this. If the number of quads is small enough then you can just test all the red quads against all the green quads, which is O(m * n).
An algorithm to perform the actual test of one rotated quad against another. One of the simplest is the Separating Axis Theorem.
The basic idea behind the SAT is that if you can find at least one line where all the points of one convex object are on one side of it, and all the points of the other are on the other side, then the two are not colliding. The potential lines that you need to test are just the edges of both of the objects.
To implement it you need to implement a point-line test to tell you which side of an edge a point is on. This is done by calculating the normal to the edge, and then calculating the dot product of the edge normal and a vector from a point on the edge to the point you are testing. The sign of the dot product tells you which side the point is on (positive means the outside the edge, for an outward pointing normal). Whether you count zero (on the line) as outside or inside depends on whether you want objects that are just touching but not penetrating to count as a collision, if you do then the dot product must be greater than zero to count as outside.
For example if the points on objects are in clockwise order, and edgeA and edgeB are the two points of an edge on one object, and pointC is a point on the other object, the test is done like this (not using function calls, to show the math):
boolean isOutsideEdge(PointF edgeA, PointF edgeB, PointF pointC)
{
float normalX = edgeA.Y - edgeB.y;
float normalY = edgeB.X - edgeA.x;
float vectorX = pointC.x - edgeA.x;
float vectorY = pointC.y - edgeA.y;
return (normalX * vectorX) + (normalY * vectorY) > 0.0f;
}
Then the algorithm is:
For each edge on quad A, if all the corner points on quad B are on the outward facing side of the edge, then A and B are not colliding, stop processing and return false.
For each edge on quad B, if all the corner points on quad A are on the outward facing side of the edge, then A and B are not colliding, stop processing and return false.
If all those tests have been performed and none have returned false, then A and B are colliding, so return true.
The SAT can be generalized to arbitrary convex polygons.
So I decided to go with box2d in the end. This was the best solution because of the diffrent mask-qualifiers, the objects didn't collide but it could be easily checked wether they should be colliding.
I had to make my own contactlistener that overrides the default contactlistener. Here I could do anything if any 2 objects collided.
Thanks everyone for the help.

Finding the distance between two objects in a 2D array, not going Diagonal

Not sure if this was posted before, but this is a relatively short question
I am currently working on a maze game being chased by something.
Currently, the player starts at (0,0), and the monster starts at (9,9). If moving is incrementing/decrementing one (not both), what is the algorithm/code to find the amount of moves it'd take for the monster to reach the main character?
From the comments I realized I should have clarified a few thing.
If the room type is 1, then it's a wall, else is open. But the main thing is that the walls do NOT impact the monster. Perhaps the better way to ask is how many moves would it take if all of the arrays were open.
You could take a look at the A* search algorithm which is widely used in games since it uses a heuristic to make performance improvements.
In your case, the heuristic could be the Manhattan Distance metric to calculate the distance between your grid elements. This distance metric takes into consideration the total of the differences in the X and Y coordinates (which unlike euclidean distance, does not allow for diagonal traversal).
To use this algorithm however, you would need to make a graph representation of your map, something like below:

Finding if an edge lies within a set of disjoint rectangles

I'm using a triangulation library to compute the Constrained Delaunay Triangulation of a set of rectangles within some large boundary. The algorithm returns all the edges, but also adds edges inside of the rectangles that define the constraints. I want to be able to find if an edge lies inside of a rectangle in O(1) time.
Here's a more general description of the problem I want to solve. Given a set of nonoverlapping rectangles (the borders of the rectangles may touch) and an edge e with endpoints (x1,y1) and (x2, y2), find in O(1) time if e lies within any of the rectangles (including the border).
Also let me know of any data structures I can use for speedups! I'm also implementing this in java so I have easy access to hash sets, maps and all those nice data structures.
Since the rectangles are completely enclosed, the inside of each rectangle will simply be the CDT of the rectangle itself -- which is to say, two triangles, meeting along a diagonal of the rectangle. So you can just insert all rectangles' diagonals (remember, two possible diagonals per rectangle) into a hashtable, and check which edges exactly match those endpoints.
It is possible to break up the area that all of the rectangles cover into a N by M grid of boxes. By labeling each box with the rectangle it is in or the rectangles it overlaps. It is possible to obtain O(1) queries, with O(N*M) pre-processing.
However, in order for it to work, the grid has to created based on an algorithm that allows for calculating which box a point lies in in O(1). It also requires that the number of rectangles a box overlaps be very small (ideally no more than 2 or 3) as otherwise the average query time could be O(log N) or worst. This means that the number of boxes can get very large.

Finding the intersection of 2 arbitrary cubes in 3d

So, I'd like to figure out a function that allows you to determine if two cubes of arbitrary rotation and size intersect.
If the cubes are not arbitrary in their rotation (but locked to a particular axis) the intersection is simple; you check if they intersect in all three dimensions by checking their bounds to see if they cross or are within one another in all three dimensions. If they cross or are within in only two, they do not intersect. This method can be used to determine if the arbitrary cubes are even candidates for intersection, using their highest/lowest x, y, and z to create an outer bounds.
That's the first step. In theory, from that information we can tell which 'side' they are on from each other, which means we can eliminate some of the quads (sides) from our intersection. However, I can't assume that we have that information, since the rotation of the cubes may make it difficult to determine simply.
My thought is to take each pair of quads, find the intersection of their planes, then determine if that line intersects with at least one edge of each of the pairs of sides. If any pair of sides has a line of intersection that intersects with any of their edges, the quads intersect. If none intersect, the two cubes do not intersect.
We can then determine the depth of the intersection on the second cube by where the plane-intersection line intersects with its edge(s).
This is simply speculative, however. Is there a better, more efficient way to determine the intersection of these two cubes? I can think of a number of different ways to do this, and I can also tell that they could be very different in terms of amount of computation required.
I'm working in Java at the moment, but C/C++ solutions are cool too (I can port them); even psuedocode since it is perhaps a big question.
To find the intersection (contact) points of two arbitrary cubes in three dimensions, you have to do it in two phases:
Detect collisions. This is usually two phases itself, but for simplicity, let's just call it "collision detection".
The algorithm will be either SAT (Separating axis theorem), or some variant of polytope expansion/reduction. Again, for simplicity, let's assume you will be using SAT.
I won't explain in detail, as others have already done so many times, and better than I could. The "take-home" from this, is that collision detection is not designed to tell you where a collision has taken place; only that it has taken place.
Upon detection of an intersection, you need to compute the contact points. This is done via a polygon clipping algorithm. In this case, let's use https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
There are easier, and better ways to do this, but SAT is easy to grasp in 3d, and SH clipping is also easy to get your head around, so is a good starting point for you.
You should take a look at the field of computer graphics. They have many means. E.g. Weiler–Atherton clipping algorithm. There are also many datastructures that could ease up the process for you. To mention AABBs (Axis-aligned bounding boxes).
Try using the separating axis theorem. it should apply in 3d as it does in 2d.
If you create polygons from the sides of the cubes then another approach is to use Constructive Space Geometry (CSG) operations on them. By building a Binary Space Partitioning (BSP) tree of each cube you can perform an intersection on them. The result of the intersection is a set of polygons representing the intersection. In your case if the number of polygons is zero then the cubes don't intersect.
I would add that this approach is probably not a good real time solution, but you didn't indicate if this needed to happen in frame refresh time or not.
Since porting is an option you can look at the Javascript library that does CSG located at
http://evanw.github.io/csg.js/docs/
I've ported this library to C# at
https://github.com/johnmott59/CGSinCSharp

Representing a 3-dimensional Grid of Spheres

Overall goal: Given a list of points in 3-dimensional space, I need to generate a sphere around that point given the point's radius and then pro grammatically check if there is space between two or more spheres given a certain point.
Problem: I'm having trouble thinking of a data structure to represent a grid of points (that represent the center of the sphere) and the surrounding sphere, these may not always be hole numbers.
Example Data:
Point A: (-3, .25, 4) Radius: 1.35
Point B: (5, 6.35, 1) Radius: 2
Point C: (1, 0, -1) Radius: .5
My original idea was to have a 3-dimensional array of integers that was of size the absolute value of the maximum and minimum values of the axes added together divided by the smallest accuracy you wanted. You would then use a conversion factor to convert from the array location (whole integers) to the decimal location of a point you were looking for. I would then fill in the array with some data to represent that a sphere exists around the sphere center.
What I'm looking for is the data structure I should use to represent this 3d grid of non-whole numbers. I feel like my technique isn't correct.
This is in Java.
Any and all help is greatly appreciated, thanks!
Why not just represent them with the 3 coordinates x,y,z (3d-point) and the radius, just as you listed them and use (3dimensional) distance to evaluate if points are inside a sphere or not?
Or am I missing the use case here? This sounds like it: "check if there is space between two or more spheres given a certain point"
I actually did something very similar earlier this week.
What I did is decide the minimum distance two points are allowed to have (here for you found by adding the radii of your two spheres if I understood you correctly). Using this I created a random field of spheres using a starting sphere at (0, 0, 0) and then incrementally add extra spheres a random distance away from that.
Since in my case (not sure if you need this as well) I also had a maximum distance I just shifted the coordinates of one of the already accepted spheres and check whether the distances matched.
So, to summarize:
Have a starting point
Randomly place a point (within a specific range) to one of your existing points
Check if it meets your spacing restrictions
Repeat 2-3 until you have enough spheres.
Hope that's any help to anybody.

Categories