I am implementing collision detection in my game, and am having a bit of trouble understanding how to calculate the vector to fix my shape overlap upon collision.
Say for example, I have two squares. squareA and squareB. For both of them, I know their xCo, yCo, width and height. squareA is moving however, so he has a velocity magnitude, and a velocity angle. Let's pretend I update the game once a second. I have illustrated the situation below.
Now, I need a formula to get the vector to fix the overlap. If I apply this vector onto the red square (squareA), they should not be overlapping anymore. This is what I am looking to achieve.
Can anyone help me figure out the formula to calculate the vector?
Bonus points if constructed in Java.
Bonus bonus points if you type out the answer instead of linking to a collision detection tutorial.
Thanks guys!
Also, how do I calculate the new velocity magnitude and angle? I would like sqaureA to continue moving along the x axis (sliding along the top of the blue square)
I had an function that looked something like this:
Position calculateValidPosition(Position start, Position end)
Position middlePoint = (start + end) /2
if (middlePoint == start || middlePoint == end)
return start
if( isColliding(middlePont) )
return calculateValidPosition(start, middlePoint)
else
return calculate(middlePoint, end)
I just made this code on the fly, so there would be a lot of room for improvements... starting by not making it recursive.
This function would be called when a collision is detected, passing as a parameter the last valid position of the object, and the current invalid position.
On each iteration, the first parameter is always valid (no collition), and the second one is invalid (there is collition).
But I think this can give you an idea of a possible solution, so you can adapt it to your needs.
Your question as stated requires an answer that is your entire application. But a simple answer is easy enough to provide.
You need to partition your space with quad-trees
You seem to indicate that only one object will be displaced when a collision is detected. (For the case of multiple interpenetrating objects, simply correct each pair of objects in the set until none are overlapping.)
Neither an elastic nor an inelastic collision is the desired behavior. You want a simple projection of the horizontal velocity (of square A), so Vx(t-1) = Vx(t+1), Vy(t-1) is irrelevant and Vy(t+1)=0. Here t is the time of collision.
The repositioning of Square A is simple.
Define Cn as the vector from the centroid of A to the vertex n (where the labeling of the vertices is arbitrary).
Define A(t-1) as the former direction of A.
Define Dn as the dot product of A(t-1) and the vector Cn
Define Rn as the width of A measured along Cn (and extending past the centroid in the opposite direction).
Define Sn as the dilation of B by a radius of Rn.
Let j be the vertex of B with highest y-value.
Let k be the vertex that is most nearly the front corner of A [in the intuitive sense, where the value of Dn indicates that Ck is most nearly parallel to A(t-1)].
Let K be the antipodal edge or vertex of A, relative to k.
Finally, translate A so that k and j are coincident and K is coincident with Sk.
Related
So I have a bounded plane (X axis range 0-1000, Y axis range 0-2000).
there are multiple points (x,y) in it, and a rectangle (4 points that makes the rectangle). Some points are in the rectangle and some aren't. like this:
The rectangle is able to move and change it's size over time. while the points are static and won't change. I need to check what points are inside the rectangle after it changes.
Problem:
Giving a rectangle, what points are inside of it?
Set<Point> getPointsInsideRectangle(Rectangle rec);
My naive solution:
for each point
check if it inside the rectangle, if yes, add the point to a Point Set
return the Point Set
My thoughts:
It seems that iterating over all the points everytime the rectangle changes seems extremely not efficient with big CPU usage (there are many points). Something tells me to use HashMap but since the rectangle is a X range and a Y range (and not just 1 value), it seems I cannot use it.
My questions:
1. Is there a java data structure that can handle this situation?
2. if not, any thoughts on how to implement a data structure that holds all the points, and giving a rectangle, returns the points in it?
Just some random thoughts:
May try to create some kind of container for a specific range, like x from 0 to 100 and y from 0 to 100 l and repeat that with more containers like x from 100 to 200 and y from 0 to 100 etc and add your points to where they belong to.
Something like
Class Container
{
Int minX;
Int maxX
Int minY;
Int maxY;
List<Point> points;
Check(int x, int y)
(
return x >= minX && x <= maxX && y >= minY && y <= maxY;
)
}
Let's call the 4 points of the rectangle A (upper left), B (upper right), C (bottom right) and D (bottom left).
Start to check all containers with A.X and A.Y and then add the default range of a container to A.X and check again all containers that are not already in your bounds. Repeat till there's less than the default range left to B.X and then add what's left.
Same from A.X and A.Y to D.X and D.Y with Y decreased by the default container range and so on and so on.. .
Maybe even create containers containing containers to scale down the amount of comparissions even more.
This way you can check for containers which overlap with your rectangle and compare the points which are in these containers.
May even use multithreading to check the containers.
(Sorry for bad editing, I'm on my phone)
Edit
Now that I reread that, I think this could results in a kind of tree structure
update
A tree seems like the right thing to go for here: Range Tree (Wikipedia)
Example implementation: Java Range tree example ( by Robert Sedgewick and Kevin Wayne. )
K-d tree (2d case) could be the starting point. It's rather simple to implement and fast enough.
Sample visualization:
Some links to java implementations: KDTree Implementation in Java
As other mentioned already, there are many data structures for spatial index:
Quadtrees
R-Trees (an R*Tree is an improved R-Tree)
KD-Trees
You have to perform a window query (sometimes called rectangle query or range query) on the index, where the query rectangle would be exactly your moving rectangle.
If you are looking for various implementations of such spatial data structures, have a look here (R*Tree, quadtrees, STR-loaded R-Tree), Or have a look at the PH-Tree, it is similar to a quadtree but much more efficient and inherently limited depth.
I've created a text based game which automatically generates a map with 10x10 rooms, a few of the rooms are blocked by various debris and I couldn't work out the most efficient way to check if a player can still reach a key and get to the exit without them being cut off from the map.
Currently there's a low chance needed rooms are cut off from the rest of the map, making the level impossible, I thought about checking each adjacent square to the start position, and then repeat and repeat until all of the squares that are accessible are set to 'accessible' in a variable and then if the three objects aren't reachable just regen'ing the map again until they are.
This may be slow if it regens a few times though.
Does anyone have any thoughts on the repetitive part to keep it fast, or a better way of achieving this?
Here's an image of a generated map: #'s are blocked rooms.
http://postimg.org/image/8oo88jxgb/
You can use the Dijkstra's algorithm, or some other pathfinding algorithm, to check if there is a way from the room entrance to each object and then discard the invalid rooms. This would probably be a bit slow though, specially if the rooms get bigger or you add more objects.
A better option would be to guarantee by construction that each part of the room can be reached. This can be achieved using Binary Space Partioning (BSP). It can be used to create random dungeons while assuring that all the rooms are connected. You can find more information in this tutorial.
There is a lot of material about procedurally generated dungeons around. You can check another interesting tutorial here.
The real problem is that programmers have spent far too much time
worrying about efficiency in the wrong places and at the wrong times;
premature optimization is the root of all evil (or at least most of
it) in programming.
Donald Knuth (1974 Turing Award Lecture, Communications of the ACM 17 (12), (December 1974), pp. 667–673)
Taking Knuth's advice, I recommend implementing the simplest solution that comes to mind (as outlined in the question, for example) and only looking for a more efficient algorithm if that approach turns out to be a bottleneck in the program. If he was right for computers with the performance they had in 1974, he's much more right now ...
You could represent your board as a graph holding a coordinate value as the key and a set of coordinates as the values representing each coordinates neighbors..example Map<Coordinate, HashSet<Coordinate> = new Hashmap<Coordinate, HashSet<Coordinate>();.
Then populate the graph with each coordinate value as a key with their respective neighbors as their values.
Whenever a blocked off room appears, simply remove that coordinate from each of the coordinates neighbors that surround it.
So if you have coordinate (5,5) as a blocked room, you would removed (5,5) from (4,5)s neighbor set, (5,4)s neighbor set, (6,5)s neighbor set, and (5,6)s neighbor set. This would basically not allow you to move through this path any more.
To populate the graph you could use two loops:
for(int r = 0; r <= 10; r++){
for(int c = 0; c <= 10; c++){
HashSet<Coordinate> neighbors = new HashSet<Coordinate>();
if(r > 0){
neighbors.add(new Coordinate(r - 1, c));
}
if(r < 8){
neighbors.add(new Coordinate(r + 1, c));
}
if(c > 0){
neighbors.add(new Coordinate(r, c - 1));
}
if(c < 8){
neighbors.add(new Coordinate(r, c + 1));
}
graph.put((new Coordinate(r,c)), neighbors);
}
}
I hope this is what you were asking for.
Make an array A with a row for each room and a column for each room.
Put a 1 in each i, j (row,column) position if the two rooms are connected.
This matrix( A ) is the numeric representation of the graph that is your game, the nodes of the graph are rooms and the edges are doors.
Now take a vector with a length corresponding to the number of rooms you have and fill it with zeros except for a one in the position corresponding to the room you start in. This vector( P ) is the number of ways you can get to a given room after 0 transitions. To check if it is possible to get to a given room in ( n )transitions simply multiply P A^n and look for a non zero value in the position in the vector that represents the given room.
this is a generalization of maths described well here https://en.wikipedia.org/wiki/Markov_chain
I'm trying to implement the absolute rank-file distance described on Knight-Distance from the Chess Programming Wiki, but I'm a little confused on what ints a and b are supposed to be in
int knightDistance(int a, int b).
Don't you need two sets of coordinates to figure this out (start location and destination)?
I thought maybe they were using 0,0 as the start and then you just give the difference between start and end locations, but that gives bad output.
How is this supposed to work, and does this algorithm work for any size grid, or just 8×8?
I believe that a and b are the rank and file distance deltas from the current position. From symmetry, only the difference between the current position and the desired destination matter.
I'm trying to write a 2D game in Java that uses the Separating Axis Theorem for collision detection. In order to resolve collisions between two polygons, I need to know the Minimum Translation Vector of the collision, and I need to know which direction it points relative to the polygons (so that I can give one polygon a penalty force along that direction and the other a penalty force in the opposite direction). For reference, I'm trying to implement the algorithm here.
I'd like to guarantee that if I call my collision detection function collide(Polygon polygon1, Polygon polygon2) and it detects a collision, the returned MTV will always point away from polygon1, toward polygon2. In order to do this, I need to guarantee that the separating axes that I generate, which are the normals of the polygon edges, always point away from the polygon that generated them. (That way, I know to negate any axis from polygon2 before using it as the MTV).
Unfortunately, it seems that whether or not the normal I generate for a polygon edge points towards the interior of the polygon or the exterior depends on whether the polygon's points are declared in clockwise or counterclockwise order. I'm using the algorithm described here to generate normals, and assuming that I pick (x, y) => (y, -x) for the "perpendicular" method, the resulting normals will only point away from the polygon if I iterate over the vertices in clockwise order.
Given that I can't force the client to declare the points of the polygon in clockwise order (I'm using java.awt.Polygon, which just exposes two arrays for x and y coordinates), is there a mathematical way to guarantee that the direction of the normal vectors I generate is toward the exterior of the polygon? I'm not very good at vector math, so there may be an obvious solution to this that I'm missing. Most Internet resources about the SAT just assume that you can always iterate over the vertices of a polygon in clockwise order.
You can just calculate which direction each polygon is ordered, using, for example, the answer to this question, and then multiply your normal by -1 if the two polygons have different orders.
You could also check each polygon passed to your algorithm to see if it is ordered incorrectly, again using the algorithm above, and reverse the vertex order if necessary.
Note that when calculating the vertex order, some algorithms will work for all polygons and some just for convex polygons.
I finally figured it out, but the one answer posted was not the complete solution so I'm not going to accept it. I was able to determine the ordering of the polygon using the basic algorithm described in this SO answer (also described less clearly in David Norman's link), which is:
for each edge in polygon:
sum += (x2 - x1) * (y2 + y1)
However, there's an important caveat which none of these answers mention. Normally, you can decide that the polygon's vertices are clockwise if this sum is positive, and counterclockwise if the sum is negative. But the comparison is inverted in Java's 2D graphics system, and in fact in many graphics systems, because the positive y axis points downward. So in a normal, mathematical coordinate system, you can say
if sum > 0 then polygon is clockwise
but in a graphics coordinate system with an inverted y-axis, it's actually
if sum < 0 then polygon is clockwise
My actual code, using Java's Polygon, looked something like this:
//First, find the normals as if the polygon was clockwise
int sum = 0;
for(int i = 0; i < polygon.npoints; i++) {
int nextI = (i + 1 == polygon.npoints ? 0 : i + 1);
sum += (polygon.xpoints[nextI] - polygon.xpoints[i]) *
(polygon.ypoints[nextI] + polygon.ypoints[i]);
}
if(sum > 0) {
//reverse all the normals (multiply them by -1)
}
How to find if a point exists in which given set of polygons ?
I have coordinates like
polygonA = 1(0,0),2(0,5),3(3,4),4(3,5),5( 2,2)
polygonB = 1(10,10),2(10,15),3(13,14),4(13,15),5(12,12)
I have a point as (6,4) now want to search if this point is in any of this polygon or in both or nearest to which polygon.
How to store such data (polygon) ? is there a system / database / algorithm to do this search ?
Update : Thanks all for such fast response...I think i need to be more specific...
How to search = Yes...got list of algorithms and library for the same.
How to store = based on my research SQL and NoSQL db have their solutions.
NoSQL = MongoDb seems closest what i needed. But issue is I can query like "db.places.find({ "loc" : { "$within" : { "$polygon" : polygonB } } })" But cant make query like db.places.find({ "loc" : { "$within" : { } } })
SQL checked postgre and openGIS for some help. But colud not figureout if its possible.
If someone can help me with that...Thanks in advance.
The basic method (if you have a small number of polygons) is to store all polygons in a collection and loop over the elements to check if a point is inside a polygon.
On the other hand, if you have a considerable number of polygons, I would recommend using an R-tree data structure, which is not available in the standard library. You should check this project, if you want to go with R-tree option: http://sourceforge.net/projects/jsi/.
R-tree allows you to index rectangles (bounding boxes of the polygons in this case). So you can find a small number of candidate polygons very fast using R-tree. Then you can loop over the candidate list to get the final result.
You can use the GeneralPath class to help you with deciding if a point intersects a polygon. First, create a GeneralPath with your coordinates added:
GeneralPath gp = new GeneralPath();
double[] x = ...
double[] y = ...
gp.moveTo(x[0], y[0]);
for (int i =1; i < x.length; i++) {
gp.lineTo(x[i], y[i]);
}
gp.closePath();
if (gp.contains(pointX, pointY)) {
...
}
For the problem of which polygon a point is nearer to, this depends a little on how accurately you need a solution.
For an accurate solution., this amounts (without optimisation) to:
take the shortest distance between the point and each of the lines (segments) connecting the vertices of each of the polygons (Java2D apparently doesn't provide a method for this, but the shortest distance from a point to a line is a fairly simple calculation)
which polygon has the line with the shortest distance to the point?
In practice, you can approximate this process for some applications. For example, you could much more efficiently do this:
take the centre point of the bounding rectangle of each polygon (GeneralPath.getBounds() will give you this)
take the distance between the query point and each of these centre points, and see which is closest.
If you do need an accurate answer, then you can combine these techniques to optimise your search among all the vertices. For example, you could order the polygons by the distance to their "centrepoint" (defined as above). Search from minimum to maximum distance. If the minimum distance to a segment that you have found so far is d, then you can automatically rule out any polygon P where the distance from your query point to its "centrepoint" is d + r, where r is half the length of the diagonal of P's bounding rectangle (in other words, for simplicity, you imagine a bounding circle around that bounding box and check that the distance to that bounding circle is further than the nearest point found so far on other polygons).
I don't quite understand the bit about the database. Your polygons are just defined as a series of points. How you decide to store these in memory/file doesn't essentially make any difference to the algorithm.