I want to make a game where the character is a rectangular prism that can be rotated, and the rest of the map are axis-aligned rectangular prisms. Everything other than the character will be static, so I was wondering what would be the best algorithm for finding if the character is colliding with any parts in the map. Any tutorials/code/advice would be much appreciated :)
Also, the character will only be rotated on the Y axis, if that helps.
In the special case that the character only rotates around its axis parallel to the Y-axis, the collision detection with another axis-aligned rectangular prism reduces to:
Check if the character's Y-interval intersects the other prism's Y-interval.
Check if the corresponding XZ-cross-sections of the two prisms intersect, which amounts to a problem of collision detection between two rotated rectangles.
If the answer to both the above is yes, then and only then do the prisms overlap.
Having reduced the particular problem to that of overlapping intervals and intersecting (rotated) rectangles, there are a number of good code resources for each of these tasks. The first task is pretty trivial:
Overlapping intervals
Two closed intervals [a,b] and [c,d] intersect if and only c ≤ b and a ≤ d. Here we also assume the intervals' notation is consistent, i.e. that a ≤ b and c ≤ d (otherwise swap the endpoints as necessary to make it so).
Intersecting rotated rectangles
A highly rated SO answer to this specific question is here. A Lua implementation I wrote for a slightly more general problem, Shortest distance between two rectangles, includes "early exit" optimizations (bounding circle and vertex in rectangle) that I mentioned on this thread. My Lua code returns "false" if the rotated rectangles intersect, otherwise the distance between them. For Java purposes the return value of zero in the collision cases would serve.
I believe one way to test for this is to check the 16 cases of line intersections:
http://www.math.niu.edu/~rusin/known-math/95/line_segs
If you want to optimize you could also check if the rectangles have no chance of overlapping, i.e. if all corners are to the right/left/above/below of the other rectangle.
Edit:
Se comment below.
Related
This is a question from a mind games book. I tried solving it like this (http://pastebin.com/sdfcuxW1) but had no luck. It also has to be very optimized to process outputs for 2000 input coordinates under 4 seconds.
Any suggestions about my code, or any new algorithm ideas would be very helpful.
Question:
We have a coordinate plane, and we are only using the first quadrant. We are supplied with a number of coordinates each with +X and +Y values. For example 0,2 - 5,4 etc. We are required to connect each of these coordinates with rectangles (one corner of the rectangle touches one coordinate and another corner touches another coordinate) so that all coordinates are in contact with each other (no left-outs). We also have to make sure that the rectangles that we use to connect our 2 coordinates do not overlap with any other coordinate (on the edges is fine). What kind of algorithm can print out the best solution to this problem, given that the goal is to use the smallest total rectangle area possible.
http://cl.ly/image/1P012s3p1E1g
purple areas are rectangles and green dots are coordinates. we can have rectangles which have 0 height of width, which consume no area.
What I couldn't figure out: find the closest coordinates to our starting coordinate is easy. but it is hard to make sure that all coordinates are connected together. i always get pieces of coordinates floating in different areas of the plane. my code also lags with >1000 points.
Here is a solution:
Let's model this problem as a graph problem.
The vertices are the given points.
There is an edge between every pair vertices. The weight of this edge is the area of the rectangle formed by this pair of points.
The answer is the minimum spanning tree in this graph. We can use Prim's algorithm to find it.
The time complexity of this solution is O(n ^ 2).
The only question is: why can't a rectangle generated by this algorithm contain another point? I will not post a formal proof here, but drawing some pictures shows that if there is such a rectangle, the solution is not optimal(an idea of a proof: let's assume that there is a point inside. We can split this rectangle into two so that this points becomes one of their corner. The total area can only decrease after performing this operation).
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
I'm trying to fit two ellipses to what happens to be the top view / outline of a body. For simplicity let's use the following example:
As you can see, this simple body is made up of a long core (blue) and a head (red). In reality this outline would be in one color, I'm just using two colors for visualization purposes here.
I know how to fit a single ellipse to either parts of that outline, but I do not know how to do the fit to two ellipses, given the constraint that these two ellipses are actually connected. In this particular case the constraint is that the two ellipses will never part and that there can only be a certain angle between ellipse 1 and ellipse 2.
I'm grateful for any pointers that tell me how to write a function, so that after calling magic_fitting_function(body_outline) the program returns to me the coordinates of the two underlying ellipses:
EDIT1:
what is are the minimal requirements that could make solving this problem easier? E.g. if I were given one point, two points, etc, how would that possibly simplify the problem?
EDIT2:
I'm looking for a programming language independent solution.
EDIT3:
any hints on how to formulate the constraint of these two ellipses being located in a certain relationship to each other programmatically? E.g.: I know that the small ellipse will always be located at one end of the major axis of the big ellipse. Plus the small ellipse can only rotate by +- 90 degrees relative to the big ellipse.
I have never solved this problem, so I'm just throwing out a suggestion.
First, generate a bounding ellipse for the entire figure in order to determine what are the topmost and the bottommost points. (This step may not be necessary if you have a better way of finding these points.)
Next, detect the location of the "neck" by using a modified binary search. (Here I'm assuming that your bounding ellipse has a vertical orientation, as though the figure were standing up or standing on its head.) Generate two sets of bounding ellipses: one with an ellipse from the top of the figure to the 1/4 point of the figure (meaning if you draw a line through the bounding ellipse then the 1/4 point is between the top-left point and the middle) and with an ellipse from the 1/4 point to the bottom of the figure, and one with an ellipse from the top of the figure to the 3/4 point and with an ellipse from the 3/4 point to the bottom of the figure; the set of ellipses with the smaller total area is the one that is better encapsulating the head. Continue the search (e.g. next test an ellipse from the top to the 1/8 point / 7/8 point, and/or from the top to the 3/8 point / 5/8 point) until you've minimized the total bounding area of the set of ellipses; the point at which the ellipses meet is the neck. (No need to be too precise with this, it probably doesn't make much difference if you put the neck at the 34/256ths point or at the 35/256ths point.)
To detect the neck you may want to use bounding boxes instead of bounding ellipses.
Finally, adjust the two bounding ellipses in order to meet their angle constraints, e.g. by moving their extreme points in 5% increments (so assuming that the head ellipse's extreme points are on the y-coordinates 0 and 50 and the body ellipse's extreme points are on the y-coordinates 50 and 200, adjust them so that their extreme y-coordinates are on 0 and 60 and on 40 and 200).
If you have the complete outline, you can find where the two ellipses intersect - just look for the two sharp corners where the first derivative of your outline becomes discontinuous. Then, draw a straight line between those corners.
Everything on one side of the line is in ellipse A, everything on the other side is in ellipse B. The sharp corners are in both ellipses. Now, just fit a single ellipse to each of the two ellipses you've found and recalculate the points where the fitted ellipses intersect.
You can try isolating ellipses using the Hough transform. There are some FEX tools out there that are worth trying, for example this Ellipse Detection Using 1D Hough Transform.
Find the two points that are furthest from each other. One will belong to Ellipse1, the other to Ellipse2.
Check the nearest neighbors of these points to get 5 points belonging to Ellipse1, and 5 to Ellipse2.
Check out Wikipedia, and choose your favorite equation of an ellipse.
Using junior high algebra, for each ellipse, plug in the points to get 5 simultaneous equations, and solve these to get the 5 parameters that define your ellipse.
EDIT
I didn't realize this was tagged "matlab". In that case, once you have identified some points for each ellipse, there are matlab functions for fitting the points to an ellipse.
I bring you a maybe complex question which i would love your help with. Allow me to go straight to the point:
I desire an algorithm or logic in which i draw a shape using my mouse (for example a square) and it becomes a perfect square, with all the 4 sides in straight lines and perfectly regular. A human-drawn square is hardly perfect, but i wish that after it goes through the "filter" of this algorithm ,it becomes such.
A fine example of what i wish is in the game Trine, where the Wizard works by a similar principle: You draw a shape in the screen and it becomes the closest shape, that is, if you draw something similar to a square it becomes a perfect square box, but if you draw a triangle it becomes a perfect triangular box. Its like it detects what kind of shape it is and then draws a better version of it.
I want this for a game, just so you know what is the goal of all this.
Please help me figure out either the algorithm or logic behind this, or at least tell me what is the name of this kind of action (:
P.S. i added a simple image so it becomes even more clear what i intend =)
If I had to implement this task, I would store the recognizable patterns, and would try to make a match for them.
Take the minX, maxX, minY, maxY values form the user-drawn points, that will help you to scale the pattern. Choose the scaling so that the aspect ratio for the pattern would be the average of the X and Y aspect ratios.
The patterns can consist of certain number of straight lines. The pattern matches if
There are no points outside of the threshold
There is at least one user-drawn point close to each key points in the pattern
If you have the pattern matched, you will have the key points for your pattern (calculating the center of your pattern, and the size/aspect ratio). Then you can replace the user-drawn points with your image - that may be totally different from the pattern used to match (imagine a circle).
There are many ways to do this. One way that you could do it is to create a neural net that recognizes these shapes. I would generate variations of circles, squares, lines, and triangles with random perturbations to replicate "hand-drawn" versions. Then you would want to represent this as a two-dimensional array (where locations that have been drawn on would be 1's and locations that haven't been drawn on, would contain 0's). You can then convert this two-dimensional array into an input vector of n x n elements. The output of the neural net would be a vector with four elements, each one representing either a line, circle, square, or triangle. You would then train this neural net using your randomly-perturbed images until you end up with a neural net that recognizes the input with an error that is under some error-threshold. This is actually quite similar to recognizing handwritten digits.
Other ways include:
Shape contexts.
k-means clustering
Support vector machines
You don't have just an arbitrary shape, you also have the shape's path. So try counting corners. Decide on a angle threshold that will represent a corner. For each point, sample the next consecutive x number of points. Measure the angle between the first half and second half. If the angle surpasses your threshold, consider it a corner. (Obviously select the point that give you the best angle with the least amount of error, not just the first one that surpasses the threshold.) Mark the location of the corners and draw your shape to match.
Ellipses & lines: if no angles are detected, sample a few segments. Measure the orientation. If they are very similar, then line. If very different, then ellipse. If ellipse, find the bounding box and draw inside.
Problem: Given a list of spheres, find all empty spaces that are completely enclosed by spheres.
Detail: This is a problem I am working on in which I try to determine the cavities located in a protein. I am given a list of atoms that make up the protein ((x,y,z) coordinates and radius). I then run my algorithm to find all empty spaces that lie within the bounds of the protein by checking if a probe (of given radius) can be placed at a location without colliding with other spheres. There are two types of empty spaces, void spaces and cavities. Void spaces are spaces that can lead to or on the outside of the protein. Cavities are empty spaces that are completely enclosed by protein atoms. Here is an image of the sample "protein" we are working with.
It can be viewed in three dimensions here.
There is a cavity located near the center of the protein, the tunnel you see going through the protein would be considered a void space because it is not fully enclosed by atoms.
Example: Given a list of 26 atoms, these atoms are evenly spaced from (0,0,0) to (1,1,1) in a 3-dimensional grid. Each atom has a radius of 0.25 and is placed on either 0, 0.5, or 1 on any axis. There is no atom at the point (0.5, 0.5, 0.5). If we were to draw a 3D figure of these atoms, it would be a cube like shape with the center missing. A cavity would be designated at (0.5,0.5,0.5) with a radius of 0.25. It can be assumed that this cavity is surrounded by proteins on all sides.
Example image:
Note that the above is only a 2D representation of the cube and protein. It is actually 3D.
How would one go about determining void spaces vs. cavities for a much larger and irregularly shaped group of atoms?
I was thinking about implementing a recursive algorithm that checks every direction to see if it can reach the maximum and minimum bounds of the graph but I am not sure if this is the correct way to go about doing it.
Extra: Is there a different algorithm that would say the cavity in the example is actually a void space because there are very small "paths" to reach the outside of the protein? A cavity would have to be completely enclosed by atoms to exist. Any void spaces that have a path (in any direction, not necessarily straight) to the outside of the protein would not be considered cavities.
Cool question. Here's an algorithm that should do the trick:
Notation:
Let's call our moveable sphere S.
Write diam(X) for the diameter of a sphere X
Write dist(X,Y) for the distance from X to Y; this is the same as the distance from the center of X to the center of Y minus the sum of the radii.
The algorithm:
For any two unmoveable spheres A and B, check whether S can pass directly between the centers of A and B (i.e. is diam(S) <= dist(A,B)?).
If so, for each other sphere C, check whether S could simultaneously touch all three spheres A, B, and C, if there were no other spheres present. If S could simultaneously touch all 3, draw a triangle between the centers of A, B, and C.
This can be checked in several ways. One fairly easy way: the possible positions of the center of S while touching both A and B form a circle. You want to know whether this circle has a point on it which is less than diam(S) + diam(C) away from the center of C. This is easy geometry.
The problem now reduces to the question: do the triangles separate the initial position of the center of S from infinity? You can answer this one connected component at a time. In fact, you can even answer this one "edge-connected" component at a time, where a component is edge-connected if any two non-vertex points can be linked by a path that doesn't pass through any vertices. You can calculate these components through a simple graph search.
For a given edge-connected component, you need to decide whether the component separates the center of S from infinity. There are a few ways you might do this:
Calculate the 2-homology of the component, choose effective generators, and for each, ask whether your point and infinity are on the same side of the cycle or not, which can be checked using the orientation class.
Or, just start painting the component:
Start with a triangle that you can reach from S, and paint every face that can be reached from there. This is slightly subtle, but the algorithm is just "start anywhere, queue up the edges, cross each edge onto the face forming the smallest angle with that edge, and stop when there are no edges left." Keep in mind that the opposite side of the same triangle might be the face forming the smallest angle.
Do the same from infinity. Did you cross any painted triangles? If yes, your sphere can escape. If no, it can't.
Why it works
Step 3 is true because if you don't hit any sphere C while "rolling around" the edge between A and B, then you can reach any side of that edge. Put another way, any position that stops you from going to infinity must involve S touching at least 3 spheres.
Note that there are some subtleties that arise from "exceptional" situations, like when S touches 4 spheres at once. You can avoid these subtleties by re-triangulating your shape before performing steps 3 and 4.