Quadrangle intersection algorithm - c#

I'm currently writing a game (2D with OpenTK) in which there is a lot of rotation, and with it comes that I sometimes need to get the intersection between these lines/shapes:
Two quadrangles http://files.myopera.com/antonijn/albums/12693002/TwoQuadrangles.png
I know the rotation (in degrees) of both of them, and therefore I know the position of all the vertices in both shapes.
The algorithm needs to give me a bool on whether they intersect, or better yet, the coordinates of the intersections.
I have written my own algorithm, which scrolls through the sides of the first box, gets the formula for each side and compares them to the formulas of the lines of the second box. Now, this doesn't work when the lines are upright (slope of float.Infinity or float.NegativeInfinity), is a pain to debug and is far from fast, so I need a better one!
Any suggestions?

I ended up using the SAT method, as suggested by Nickon, thanks a bunch mate!

Related

How to get intersection area of two polygons

Apologies for the lack of example code, I'm currently in the brainstorming phase of the problem and having trouble finding a proper solution.
As I have stated in my title, I want to find out what the intersection area of two polygon are.
To be more specific, I have two ARPlane's that may overlap each other on the x-z plane but be on different y-levels (imagine stairs with an overhang). I can get the area boundaries of these ARPlanes easily. My first idea to simplify the process is to remove the y-component so as to have them on the same plane and turn this into a 2D problem.
From here onward, I'm unsure of how to proceed. I could not find any methods that calculated the intersection areas of two polygons. I have a few solutions that look promising if I can get the planes aligned neatly (such that the +x direction points from the center of one of the planes to the other), but I cannot move them in any way so I must modify what the local "forward" for a plane is. Even then, I don't think the ARPlane has a direction vector in the first place as they are not GameObjects, so I am unsure if this is a viable option as a path to follow. ARPlane class for quick reference.
One other way is to turn the planes so that they're in alignment with world x axis. This looks promising over the other methods but as I previously stated, I cannot turn the actual ARPlanes. I must make a copy of them and turn the copies while keeping their relative rotations and positions the same.
So far these have been the methods I could come up with but could not develop fully due to unity restrictions. My question, then, is whether there is a way to get around the issues of these problems; failing that, whether there is an alternative solution to the issue that can be recommended.
Below is an example use case of the tool. As can be seen, some stair threads have an overhang that covers a portion of the previous thread's surface (second and third figure). Each stair thread will be scanned and then processed to find their usable surface. The area covered by the overhang is not a usable surface. This usable area is defined by the placements of a staircase thread (A), and the very next thread right above it (B); so then the usable area will be surface_area_of_A - xz_crossSection_of_AB

Slicing a 3D model?

I want to slice a 3D model relative to an infinite plane(In WPF). I'm checking if edges intersect with the infinite plane. If true, I'll create a new point at the intersection position, so I'm getting a couple of points that I want to generate a cap on so that the model is closed after slicing. For example, if this is the cross section, the result would be as follows:
Note: The triangulation ain't important. I just need triangles.
I also need to detect the holes as follows(holes are marked in red):
If it is impossible to do it the way I think(It seems to be so), the how should I do it? How do developers cap an object after being sliced?
There is also too much confusion. For example, The first picture's result may be:
What am I missing??
EDIT:
After some research, I knew one thing that I am missing:
The input is now robust, and I need the exact same output. How do I accomplish that??
In the past, I have done this kind of thing using a BSP.
Sorry to be so vague, but its not a a trivial problem!
Basically you convert your triangle mesh into the BSP representation, add your clipping plane to the BSP, and then convert it back into triangles.
As code11 said already you have too few data to solve this, the points are not enough.
Instead of clipping edges to produce new points you should clip entire triangles, which would give you new edges. This way, instead of a bunch of points you'd have a bunch of connected edges.
In your example with holes, with this single modification you'd get a 3 polygons - which is almost what you need. Then you will need to compute only the correct triangulation.
Look for CSG term or Constructive Solid Geometry.
EDIT:
If the generic CSG is too slow for you and you have clipped edges already then I'd suggest to try an 'Ear Clipping' algorithm.
Here's some description with support for holes:
https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
You may try also a 'Sweep Line' approach:
http://sites-final.uclouvain.be/mema/Poly2Tri/
And similar question on SO, with many ideas:
Polygon Triangulation with Holes
I hope it helps.
Building off of what zwcloud said, your point representation is ambiguous. You simply don't have enough points to determine where any concavities/notches actually are.
However, if you can solve that by obtaining additional points (you need midpoints of segments I think), you just need to throw the points into a shrinkwrap algorithm. Then at least you will have a cap.
The holes are a bit more tricky. Perhaps you can get away with just looking at the excluded points from the output of the shrinkwrap calculation and trying to find additional shapes in that, heuristically favoring points located near the centroid of your newly created polygon.
Additional thought: If you can limit yourself to convex polygons with only one similarly convex hole, the problem will be much easier to solve.

C# / XNA - Bounding Circle Collision (Micro) Optimization?

I've been working on a simple space shooter, and have gotten to the point in the project where my terribly written code is actually slowing things down. After running EQATEC, I can see that the majority of the problem is in the icky check everything on everything collision detection. I was considering putting in a QuadTree, but the majority of the collisions are on asteroids, which do move around a lot (would require a lot of updating). My next alternative was micro-optimizing the collision check itself. Here it is:
public bool IsCircleColliding(GameObject obj) //simple bounding circle collision detection check
{
float distance = Vector2.Distance(this.WorldCenter, obj.WorldCenter);
int totalradii = CollisionRadius + obj.CollisionRadius;
if (distance < totalradii)
return true;
return false;
}
I've heard that Vector2.Distance involves a costly Sqrt, so is there any way to avoid that? Or is there a way to approximate the distance using some fancy calculation? Anything for more speed, essentially.
Also, slightly unrelated to the actual question, is there a good method (other than QuadTrees) for spatial partitioning of fast-moving objects?
Compute the square of the distance instead of the actual distance, and compare that to the square of the collision threshold. That should be a bit faster. If most asteroids are the same size, you can reuse the same value for the collision threshold without recomputing it.
Another useful trick is to first do a simple check based on bounding boxes, and compute the distance only if the bounding boxes intersect. If they don't, then you know (for cheap) that the two objects aren't colliding.

Simple way to calculate point of intersection between two polygons in C#

I've got two polygons defined as a list of Vectors, I've managed to write routines to transform and intersect these two polygons (seen below Frame 1). Using line-intersection I can figure out whether these collide, and have written a working Collide() function.
This is to be used in a variable step timed game, and therefore (as shown below) in Frame 1 the right polygon is not colliding, it's perfectly normal for on Frame 2 for the polygons to be right inside each other, with the right polygon having moved to the left.
My question is, what is the best way to figure out the moment of intersection? In the example, let's assume in Frame 1 the right polygon is at X = 300, Frame 2 it moved -100 and is now at 200, and that's all I know by the time Frame 2 comes about, it was at 300, now it's at 200. What I want to know is when did it actually collide, at what X value, here it was probably about 250.
I'm preferably looking for a C# source code solution to this problem.
Maybe there's a better way of approaching this for games?
I would use the separating axis theorem, as outlined here:
Metanet tutorial
Wikipedia
Then I would sweep test or use multisampling if needed.
GMan here on StackOverflow wrote a sample implementation over at gpwiki.org.
This may all be overkill for your use-case, but it handles polygons of any order. Of course, for simple bounding boxes it can be done much more efficiently through other means.
I'm no mathematician either, but one possible though crude solution would be to run a mini simulation.
Let us call the moving polygon M and the stationary polygon S (though there is no requirement for S to actually be stationary, the approach should work just the same regardless). Let us also call the two frames you have F1 for the earlier and F2 for the later, as per your diagram.
If you were to translate polygon M back towards its position in F1 in very small increments until such time that they are no longer intersecting, then you would have a location for M at which it 'just' intersects, i.e. the previous location before they stop intersecting in this simulation. The intersection in this 'just' intersecting location should be very small — small enough that you could treat it as a point. Let us call this polygon of intersection I.
To treat I as a point you could choose the vertex of it that is nearest the centre point of M in F1: that vertex has the best chance of being outside of S at time of collision. (There are lots of other possibilities for interpreting I as a point that you could experiment with too that may have better results.)
Obviously this approach has some drawbacks:
The simulation will be slower for greater speeds of M as the distance between its locations in F1 and F2 will be greater, more simulation steps will need to be run. (You could address this by having a fixed number of simulation cycles irrespective of speed of M but that would mean the accuracy of the result would be different for faster and slower moving bodies.)
The 'step' size in the simulation will have to be sufficiently small to get the accuracy you require but smaller step sizes will obviously have a larger calculation cost.
Personally, without the necessary mathematical intuition, I would go with this simple approach first and try to find a mathematical solution as an optimization later.
If you have the ability to determine whether the two polygons overlap, one idea might be to use a modified binary search to detect where the two hit. Start by subdividing the time interval in half and seeing if the two polygons intersected at the midpoint. If so, recursively search the first half of the range; if not, search the second half. If you specify some tolerance level at which you no longer care about small distances (for example, at the level of a pixel), then the runtime of this approach is O(log D / K), where D is the distance between the polygons and K is the cutoff threshold. If you know what point is going to ultimately enter the second polygon, you should be able to detect the collision very quickly this way.
Hope this helps!
For a rather generic solution, and assuming ...
no polygons are intersecting at time = 0
at least one polygon is intersecting another polygon at time = t
and you're happy to use a C# clipping library (eg Clipper)
then use a binary approach to deriving the time of intersection by...
double tInterval = t;
double tCurrent = 0;
int direction = +1;
while (tInterval > MinInterval)
{
tInterval = tInterval/2;
tCurrent += (tInterval * direction);
MovePolygons(tCurrent);
if (PolygonsIntersect)
direction = +1;
else
direction = -1;
}
Well - you may see that it's allways a point of one of the polygons that hits the side of the other first (or another point - but thats after all almost the same) - a possible solution would be to calculate the distance of the points from the other lines in the move-direction. But I think this would end beeing rather slow.
I guess normaly the distances between frames are so small that it's not importand to really know excactly where it hit first - some small intersections will not be visible and after all the things will rebound or explode anyway - don't they? :)

Getting curve details from points

I have a List of 2D points. What's an efficient way of iterating through the points in order to determine whether the list of points are in a straight line, or curved (and to what degree). I'd like to avoid simply getting slopes between smaller subsets. How would I go about doing this?
Thanks for any help
Edit: Thanks for the response. To clarify, I don't need it to be numerically accurate, but I'd like to determine if the user has created a curved shape with their mouse and, if so, how sharp the curve is. The values are not too important, as long as it's possible to determine the difference between a sharp curve and a slightly softer one.
If you simply want to know if all your points fit more or less on a curve of degree d, simply apply Lagrange interpolation on the endpoints and d-2 equally spaced points from inside your array. This will give you a polynomial of degree d.
Once you have your curve, simply iterate over the array and see how far away from the curve each point is. If they're farther than a threshold, your data doesn't fit your degree d polynomial.
Edit: I should mention that iterating through values of d is a finite process. Once d reaches the number of points you have, you'll get a perfect fit because of how Lagrange interpolation works.
To test if it's a straight line, compute the correlation coefficient. I'm sure that's covered on wikipedia.
To test if it's curved is more involved. You need to know what kind of curves you expect, and fit against those.
Here is a method to calculate angle: Calculate Angle between 2 points using C#
Simply calculate angle between each and every point in your list and create list of angles, then compare if angles list values are different. If they are not different then it means it's straight line, otherwise it's curve...
If it's a straight line then angle between all points has to be a same.
The question is really hazy here: "I'd like to avoid simply getting slopes between smaller substes"
You probably want interpolation a-la B-splines. They use two points and two extra control points if memory serves me. Implementations are ubiquitous since way back (at least 1980's). This should get you underway
Remember that you'll probably need to add control points to make the curve meet the endpoints. One trick to make sure those are reached is to simply duplicate the endpoints as extra controlpoints.
Cheers
Update Added link to codeproject
it would appear that what I remember from back in the 80's could have been Bezier curves - a predecessor of sorts.

Categories