I am trying to write a Rigid body simulator, and during simulation, I am not only interested in finding whether two objects collide or not, but also the point as well as normal of collision. I have found lots of resources which actually says whether two OBB are colliding or not using separating axis theorem. Also I am interested in 3D representation of OBB. Now, if I know the axis with minimum overlap region for two colliding OBB, is there any way to find the point of collision and normal of collision? Also, there are two major cases of collision, first, point-face and second edge-edge.
I tried to google this problem, but almost every solution is only detecting collision with true or false.
Kindly somebody help!
Look at the scene in the direction of the motion (in other terms, apply a change of coordinates such that this direction becomes vertical, and drop the altitude). You get a 2D figure.
Considering the faces of the two boxes that face each other, you will see two hexagons each split in three parallelograms.
Then
Detect the intersections between the edges in 2D. From the section ratios along the edges, you can determine the actual z distances.
For all vertices, determine the face they fall on in the other box; and from the 3D equations, the piercing point of the viewing line into the face plane, hence the distance. (Repeat this for the vertices of A and B.)
Comparing the distances will tell you which collision happens first and give you the coordinates of the first meeting point (in the transformed system, the back to absolute coordinates).
The point-in-face problem is easy to implement as the facesare convex polygons.
Related
I have a set of 3d points that lie in a plane. Somewhere on the plane, there will be a hole (which is represented by the lack of points), as in this picture:
I am trying to find the contour of this hole. Other solutions out there involve finding convex/concave hulls but those apply to the outer boundaries, rather than an inner one.
Is there an algorithm that does this?
If you know the plane (which you could determine by PCA), you can project all points into this plane and continue with the 2D coordinates. Thus, your problem reduces to finding boundary points in a 2D data set.
Your data looks as if it might be uniformly sampled (independently per axis). Then, a very simple check might be sufficient: Calculate the centroid of the - let's say 30 - nearest neighbors of a point. If the centroid is very far away from the original point, you are very likely on a boundary.
A second approach might be recording the directions in which you have neighbors. I.e. keep something like a bit field for the discretized directions (e.g. angles in 10° steps, which will give you 36 entries). Then, for every neighbor, calculate its direction and mark that direction, including a few of the adjacent directions, as occupied. E.g. if your neighbor is in the direction of 27.4°, you could mark the direction bits 1, 2, and 3 as occupied. This additional surrounding space will influence how fine-grained the result will be. You might also want to make it depend on the distance of the neighbor (i.e. treat the neighbors as circles and find the angular range that is spanned by the circle). Finally, check if all directions are occupied. If not, you are on a boundary.
Alpha shapes can give you both the inner and outer boundaries.
convert to 2D by projecting the points onto your plane
see related QA dealing with this:
C++ plane interpolation from a set of points
find holes in 2D point set
simply apply this related QA:
Finding holes in 2d point sets?
project found holes back to 3D
again see the link in #1
Sorry for almost link only answer but booth links are here on SO/SE and deals exactly with your issue when combined. I was struggling first to flag your question as duplicate and leave this in a comment but this is more readable.
Contour lines (aka isolines) are curves that trace constant values across a 2D scalar field. For example, in a geographical map you might have contour lines to illustrate the elevation of the terrain by showing where the elevation is constant. In this case, let's store contour lines as lists of points on the map.
Suppose you have map that has several contour lines at known elevations, and otherwise you know nothing about the elevations of the map. What algorithm would you use to fill in additional contour lines to approximate the unknown elevations of the map, assuming the landscape is continuous and doesn't do anything surprising?
It is easy to find advise about interpolating the elevation of an individual point using contour lines. There are also algorithms like Marching Squares for turning point elevations into contour lines, but none of these exactly capture this use case. We don't need the elevation of any particular point; we just want the contour lines. Certainly we could solve this problem by filling an array with estimated elevations and then using Marching Squares to estimate the contour lines based on the array, but the two steps of that process seem unnecessarily expensive and likely to introduce artifacts. Surely there is a better way.
IMO, about all methods will amount to somehow reconstructing the 3D surface by interpolation, even if implicitly.
You may try by flattening the curves (turning them to polylines) and triangulating the resulting polygons thay they will define. (There will be a step of closing the curves that end on the border of the domain.)
By intersection of the triangles with a new level (unsing linear interpolation along the sides), you will obtain new polylines corresponding to new isocurves. Notice that the intersections with the old levels recreates the old polylines, which is sound.
You may apply a post-smoothing to the curves, but you will have no guarantee to retrieve the original old curves and cannot prevent close surves to cross each other.
Beware that increasing the density of points along the curves will give you a false feeling of accuracy, as the error due to the spacing of the isolines will remain (indeed the reconstructed surface will be cone-like, with one of the curvatures being null; the surface inside the bottommost and topmost lines will be flat).
Alternatively to using flat triangles, one may think of a scheme where you compute a gradient vector at every vertex (f.i. from a least square fit of a plane on the vertex and its neighbors), and use this information to generate a bivariate polynomial surface in the triangle. You must do this in such a way that the values along a side will coincide for the two triangles that share it. (Unfortunately, I have no formula to give you.)
The isolines are then obtained by a further subdivision of the triangle in smaller triangles, with a flat approximation.
Actually, this is not very different from getting sample points, (Delaunay) triangulating them and fitting picewise continuous patches to the triangles.
Whatever method you will use, be it 2D or 3D, it is useful to reason on what happens if you sweep the range of z values in a continous way. This thought experiment does reconstruct a 3D surface, which will possess continuity and smoothness properties.
A possible improvement over the crude "flat triangulation" model could be to extend every triangle side between to iso-polylines with sides leading to the next iso-polylines. This way, higher order interpolation (cubic) can be achieved, giving a smoother reconstruction.
Anyway, you can be sure that this will introduce discontinuities or other types of artifacts.
A mixed method:
flatten the isolines to polylines;
triangulate the poygons formed by the polylines and the borders;
on every node, estimate the surface gradient (least-square fit of a plane to the node and its neighborrs);
in every triangle, consider the two sides along which you need to interpolate and compute the derivative at endpoints (from the known gradients and the side directions);
use Hermite interpolation along these sides and solve for the desired iso-levels;
join the points obtained on both sides.
This method should be a good tradeoff between complexity and smoothness. It does reconstruct a continuous surface (except maybe for the remark below).
Note that is some cases, yo will obtain three solutions of the cubic. If there are three on each side, join them in order. Otherwise, make a decision on which to join and use the remaining two to close the curve.
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 am trying to create an algorithm for 'fleeing' and would like to first find points which are 'safe'. That is to say, points where they are relatively distant from other points.
This is 2D (not that it matters much) and occurs within a fixed sized circle.
I'm guessing the sum of the squared distances would produce a good starting equation, whereby the highest score is the furthest away.
As for picking the points, I do not think it would be possible to solve for X,Y but approximation is sufficient.
I did some reading and determined that in order to cover the area of a circle, you would need 7 half-sized circles (with centers forming a hex, and a seventh at the center)
I could iterate through these, all of which are within the circle to begin with. As I choose the best scoring sphere, I could continue to divide them into 7 spheres. Of course, excluding any points which fall outside the original circle.
I could then iterate to a desired precision or a desired level.
To expand on the approach, the assumption is that it takes time to arrive at a location and while the location may be safe, the trip in between may not. How should I incorporate the distance in the equation so that I arrive at a good solution.
I suppose I could square the distance to the new point and multiply it by the score, and iterate from there. It would strongly favor a local spot, but I imagine that is a good behavior. It would try to resolve a safe spot close by and then upon re-calculating it could find 'outs' and continue to sneak to safety.
Any thoughts on this, or has this problem been done before? I wasn't able to find this problem specifically when I looked.
EDIT:
I've brought in the C# implementation of Fortune's Algorithm, and also added a few points around my points to create a pseudo circular constraint, as I don't understand the algorithm well enough to adjust it manually.
I realize now that the blue lines create a path between nodes. I can use the length of these and the distance between the surrounding points to compute a path (time to traverse and danger) and weigh that against the safety (the empty circle it is trying to get to) to determine what is the best course of action. By playing with how these interact, I can eliminate most of the work I would have had to do, simply by using the voronoi. Also my spawning algorithm will use this now, to determine the LEC and spawn at that spot.
You can take the convex hull of your set of locations - the vertices of the convex hull will give you the set of "most distant" points. Next, take the centroid of the points you're fleeing from, then determine which vertex of the convex hull is the most distant from the centroid. You may be able to speed this up by, for example, dividing the playing field into quadrants - you only need to test the vertices that are in the furthermost quadrant (e.g., if the centroid is in the positive-x positive-y quadrant, then you only need to check the vertices in the negative-x negative-y quadrant); if the playing field is an irregular shape then this may not be an option.
As an alternative to fleeing to the most distant point, if you have a starting point that you're fleeing from (e.g. the points you're fleeing from are enemies, and the player character is currently at point X which denotes its starting point), then rather than have the player flee to the most distant point you can instead have the player follow the trajectory that most quickly takes them from the centroid of the enemies - draw a ray from the enemies' centroid through the player's location, and that ray gives you the direction that the player should flee.
If the player character is surrounded then both of these algorithms will give nonsense results, but in that case the player character doesn't really have any viable options anyway.
Given a point and a set of arbitrary 2D entities (circles, polygons, lines, polylines, arcs, etc.), does anyone know of existing strategies to:
Determine if the point is enclosed (bounded) by any combination of entities? I know that it is easy enough to do an 'inside' test on the closed shapes, but this won't always give me what I want - particularly with nested or intersecting shapes.
Find the smallest (closest?) set of lines / entities that form a closed polygon around my point? (think of a flood-fill, but without relying on colour)
I've addressed this problem in a commercial product in the past. You've asked about analytic curves, but I'll address it more generally for curves that are at least twice differentiable. Handle polygons as a set of separate line segments. There is no need to segment the curves, but if you want to you can and adapt the algorithm slightly.
Also, you might want to see my paper Matrix-Based Ellipse Geometry in Graphics Gems V to find the intersections between your ellipses.
Basic idea:
Consider a ray from your test point in the +x direction.
Now consider an ant walking along your ray from the test point.
When the ant hits the first intersection with one of the curves, it makes the sharpest left it can, and leaves an arrow at that intersection indicating the direction it's chosen. (If there is no intersection, then obviously the point isn't bounded.)
If it comes to the end of a curve, it doubles back on itself.
If there are multiple curves intersecting at that point, it chooses the curve that is most to the left.
If one or more of the curves is in fact tangent to the ray at the intersection, higher derivatives can be used decide which curve and direction to choose. (This ant knows calculus.)
Now as the ant strolls along the curves, it always makes the biggest left turn it can as above. If there is tangency between curves at the intersection, use higher derivatives to decide the one that is "most to the left". (Details are left to the ant).
In its travels, the ant may come to the starting intersection with the ray multiple times. But as soon as it finds itself proceeding in the direction of the arrow (the one it left in step 3), it's travels are done and it has traversed a "contour". The problem is reduced to deciding if the point is in that contour.
A "contour" is a topological entity. It's closed ring of "segments" connected at "vertices".
A "segment" is a piece of a curve used by the contour in a particular direction.
A "vertex" is a connection between segments. A vertex is associated with a (x, y) position on the plane, but there may be multiple vertices at the same position, one for each pair of segments in the contour that meet at that point. There is a vertex for each curve endpoint (a spur vertex), or curve-curve intersection encountered by the ant.
A contour (in this context) is not a geometric entity! Don't think of it as a simple closed path on the plane. The ant might go along a segment, get to the end, and go back the way it came--this is called a "spur" and includes two contour segments, one for either direction. Or it might go along one direction of a curve segment, wander around a bit along other curves, and return along the other direction of the segment.
So even if your set of curves has only one line in it from A to B (I'm assuming you don't have infinite lines) and your ray hits it at P, you still have the contour V0(P)-V1(A)-V2(P)-V3(B)-V0 with 4 segments V0-V1, V1-V2, V2-V3, V3-V0. Note that V0 and V2 are distinct vertices, both positioned at P.
Now to test if your point is in the contour.
Find the intersections of your ray (any ray originating at your test point will do) with the contour. We only really want the parity (even or odd) of the number of intersections with the contour. If the parity is odd, the point is bounded by the curves, if it's even it's not.
Because doubly traversed segments contribute nothing to the parity, we can ignore them. This is because there are always an even number of intersections on doubly traversed segments, since they're in the contour twice.
Examples:
Consider this curve set. I use lines so I don't work too hard:
Case 1 - The point is not bounded. The contour's use of the curve segments is indicated by the dotted arrows. The number of ray-contour intersection parity is even.
Case 2 - The point is bounded. The ray-contour intersection parity is odd.
Here's what can go wrong:
You can't find a contour for various numerical reasons. For example, you might miss intersections, e.g. two curves are almost tangent at a curve. You might see it as a single intersection, but when you do the ray intersection parity test you see a single crossing so that the parity flips when it shouldn't.
You might not be able to compute enough derivatives to make the correct turn decisions. In the case of analytic geometry this should never be the case.
Your ray hits a vertex (connections between segments) of your contour. (Note that there can be multiple vertices at a single (x, y) point. Each of these has to be handled separately.)
In this case, you have to decide if the incoming and outgoing segments of the vertex are on the same side of the ray at the vertex. If they're on the same side, the parity is not affected. Otherwise the parity flips. If one of the curves is tangent to the ray at the vertex, you may have to use higher derivatives to decide this.
A line segment is collinear with your test ray. This is actually a special case of 2, but easy to handle: Ignore it.
There are lots of details, but you should be able to handle them. Be sure to use spatial trees to avoid computing unnecessary intersections.
The answer to your second question comes from removing from the contour any doubly traversed segments. This may yield multiple sub-contours. One of them will contain your point.