There is a function Object intersection(Type1<Kernel> obj1, Type2<Kernel> obj2) in CGAL which will return an object, representing intersection of two given objects of different possible types. It is said, that intersection of CGAL::Iso_rectangle_2 (rectangle with sides parallel to the x and y axis) and CGAL::Ray_2 (oriented ray outgoing from given point) is either CGAL::Point_2 or CGAL::Segment_2 (just point or segment).
And what about the case when ray intersects rectangle in two points? Cannot see anything about it in the manual.
Answered by Sebastien Loriot in cgal-discuss mailing list:
The iso_rectangle is considered as full so that what you call
the two point case is the segment one.
Related
I have a collection of triangles that compose an arbitrary geometry (read from an OFF file). Each triangle is defined by three vertexes, which are 3D points. I have an observation point, and I want to remove from the object all those vertexes that are not visible, meaning that the segment line that joins the observation point and the vertex does not intersect with any triangle.
It is important to note that the number of vertexes and triangles in a single object is in the other of 10^4. A simple approach will be to follow [1] accepted answer, which uses the signed volumes. I have implemented it, but it includes two nested for loops: for each vertex, I need to check if the line to the observation point intersects with ANY of the triangles. Of course, I break the look when it intersects with one, but it still leads to 192M calls to the signed volume function.
Some efficient algorithms [2] assume an infinite line, not a line segment, which leads to the deletion of the vertex even if the intersection is with a further away triangle.
Any ideas on how to solve this efficiently?
[1] Intersection between line and triangle in 3D
[2] Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2, 1997, p. 21–28
Your problem statement is literally a ray-tracing problem: find if a bunch of points are occluded by the geometry or not. Therefore you can apply any ray-tracing tricks to make it fast; i.e. build some spacial index over your model and trace the rays using that spacial index. Some of the most common spacial indexes are BVH, BSP trees, or kd-trees.
If an approximate solution is good-enough, you can rasterize the geometry from the vantage point, and then test all your vertices against the generated Z-buffer.
Notice that either of these methods will filter the vertices (which is what you asked for). However, some triangles may be visible even if all their vertices are occluded. Those triangles will be removed too, even though they are visible. The rasterization method is easy to modify to filter triangles instead of vertices.
There are two question in one:
efficiency
segment-triangle intersection instead of ray-triangle intersection
efficiency
You can use a Bounding Volume Hierarchy (BVH)
The idea is to construct a hierarchy of boxes. Each box contains either other boxes or a bunch of triangles. The boxes are organized as a tree, and the root of the tree corresponds to a box that contains everything.
The function that computes an intersection works like that:
Compute the intersection between the ray and the box. If there is an intersection, open the box and recursively compute the intersections between the ray and what's in the box.
In more formal terms:
Intersect_Ray_Node(Ray, node)
if(Intersect_Ray_Box(Ray, node.box)) {
if(node.is_leaf) {
for each triangle t in node
Intersect_Ray_Triangle(Ray, t)
} else {
for each child in children(node)
Intersect_Ray_Node(Ray,child)
}
}
Now, the "boxes" can be different things. The simplest thing to use is an AABB (Axis Aligned Bounding Box), that is, simply the minimum and maximum values of the coordinates of what's in the box.
There are several ways of implementing the tree. The most efficient implementations use no data structure and simply reorder the facets in the mesh, in such a way that facets that are in the same node have contiguous indices. Then you just need a couple of additional arrays, one that stores for each node the bounds of the boxes, and another one that indicate for each node how many triangles there are in the left child (then the number of triangles in the right child is implicit).
An implementation is available here, in my geogram library. Constructing the AABB is just a matter
of sorting the triangles geometrically here and constructing the bouding box recursively.
I made also a ShaderToy implementation here (and a big comment at the end of BufferA contains the C++ source of my "MeshCompiler" that creates the AABB).
Note that if you want to be even more compact in memory, Pierre Terdiman proposed the Zero Byte AABB-tree (see here and here). The idea is to encode everything in the order of the triangles and the order of the vertices, based on the interesting remark that the bounds of the boxes are always coordinates of existing points in the mesh.
line segment versus ray
If what you want to intersect is a segment (with two vertices) instead of a ray (line that starts from a point and that extends towards infinity in a direction), you can do that with a simple modification of my answer here. Replace the last line
of the intersect_triangle() function with:
return (det >= 1e-6 && t >= 0.0 && t <= 1.0 && u >= 0.0 && v >= 0.0 && (u+v) <= 1.0);
(test that t is between 0 and 1, which means that the point is inside the segment)
I have two circles joined together like this:
And I have a point inside the shape, and I would like to cast a ray in a direction from that point onto the shape. In order to retrieve the casted position on the edge of the shape.
My first thought will be to raycast with the 2 segments joining the 2 circles. And if there is no success hit, I'll raycast with the 2 circles and take the farthest hit position. Is there a better solution? More efficient computation-wise?
Thank you for your answers
Is suppose that you have direction vector of ray D=(dx, dy) and source point is inside of capsule
If you have central axis, use it's direction vector A, otherwise get direction vector S, S of any segment.
At first decide what segment might be intersected: get cross product A x D or S x Dand look at it's sign. Positive sign denotes that you have to check only intersection with the "left" segment, negative one - intersection with the "right" segment.
I am trying to write C++ code to find the intersection points of a segment intersecting a tetrahedron. I reduced the problem like this:
For each face of the tetrahedron (a triangle), find the intersection point of the line segment. Then, I have three cases:
a) The segment doesn't intersect any face - thus either the segment is entirely in the tetrahedron or completely outside.
b) The segment only intersects one face. Then I just need to determine the side of the segment that is in the tetrahedron and I get the two points that are in the tetrahedron.
c) The segment intersects two faces.
I am having trouble implementing this algorithm. Here are the issues:
If the segment and triangle are in the same plane, how do I find the intersection points?
How can I determine if the segment lies on one of the edges of the tetrahedron?
Thanks.
Hint:
You can't avoid a complex case discussion. Here I introduce the planar case of a line segment and a triangle.
The sides of the triangle define three straight lines that partition the plane in 7 regions, one bounded and 6 unbounded. On the figure, they are designated by the signs obtained when you plug the coordinates of a point in the three implicit equations of these lines.
If you need to consider endpoints exactly on a side, you need to add 6 half-lines and 3 segments to the discussion.
Then take all possible combinations of the starting and ending regions.
Many of the cases are straightforward. When the two segment endpoint belong to the same region, the segment is wholly inside or outside; when one of the regions is +++ and the other is different, there is exactly one intersection...
In the case of the figure (--+ to ++-), you are sure to have one intersection with the bottom edge; but which is the other intersected side is unsure: to answer this, you need to tell on what side of the line segment the top vertex lies.
With some courage, you can discuss all 16 x 15 / 2 = 120 cases, many of which are identical to a permutation of the elements.
This is just an appetizer compared to the 3D problem.
"How can I determine if the segment lies on one of the edges of the tetrahedron?"
Write a function that computes the area of the triangle determined by three points in space. This can be computed from a determinant, as explained here and many other sites.
Then write a function that determines if two segments ab and cd are collinear.
They are if and only if the area of abc is zero, and the area of abd is zero.
Finally, write a function that determines if one point c lies on the segment ab. With all this, the remainder is easy.
To answer the general question, i.e. how to find the (up to two) intersections between a segment and a tetrahedron, I'd prefer to avoid the painful case-by-case analysis (mentioned in your problem reduction and in another answer).
I would use a variant of Sutherland-Hogdman's reentrant clipping (explained in 2D in [1]): the idea is to consider the tetrahedron as the intersection between four oriented half-spaces (limited by the support planes of the four faces of the tetrahedron).
Thus to compute the intersection between a segment and a tetrahedron, you can proceed as follows:
S := your segment
for f := 0 to 3 {
H := half_space(tet, f)
S := intersect(S, H)
}
H is just a plane equation (coefficients a,b,c,d of equation ax+by+cz+d=0,
[a,b,c] is the normal to the facet, oriented towards the interior of the tetrahedron. d is obtained by injecting a vertex incident to the facet into the equation).
The function intersect() is simple to implement (just test the sign of ax+by+cz+d at both vertices of the segment, if they differ, there is an intersection, that can be computed by injecting a parametric equation of S
x=x1+t(x2-x1), y=y1+t(y2-y1), z=z1+t(z2-z1) into (ax+by+cz+d=0) and solving for t, where (x1,y1,z1) and (x2,y2,z2) denote the two extremities of S.
In addition, the function intersect() may compute two booleans, to keep track of which vertex of S is a generated intersection.
[1] https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
Imagine an enormous 3D grid (procedurally defined, and potentially infinite; at the very least, 10^6 coordinates per side). At each grid coordinate, there's a primitive (e.g., a sphere, a box, or some other simple, easily mathematically defined function).
I need an algorithm to intersect a ray, with origin outside the grid and direction entering it, against the grid's elements. I.e., the ray might travel halfway through this huge grid, and then hit a primitive. Because of the scope of the grid, an iterative method [EDIT: (such as ray marching) ]is unacceptably slow. What I need is some closed-form [EDIT: constant time ]solution for finding the primitive hit.
One possible approach I've thought of is to determine the amount the ray would converge each time step toward the primitives on each of the eight coordinates surrounding a grid cell in some modular arithmetic space in each of x, y, and z, then divide by the ray's direction and take the smallest distance. I have no evidence other than intuition to think this might work, and Google is unhelpful; "intersecting a grid" means intersecting the grid's faces.
Notes:
I really only care about the surface normal of the primitive (I could easily find that given a distance to intersection, but I don't care about the distance per se).
The type of primitive intersected isn't important at this point. Ideally, it would be a box. Second choice, sphere. However, I'm assuming that whatever algorithm is used might be generalizable to other primitives, and if worst comes to worst, it doesn't really matter for this application anyway.
Here's another idea:
The ray can only hit a primitive when all of the x, y and z coordinates are close to integer values.
If we consider the parametric equation for the ray, where a point on the line is given by
p=p0 + t * v
where p0 is the starting point and v is the ray's direction vector, we can plot the distance from the ray to an integer value on each axis as a function of t. e.g.:
dx = abs( ( p0.x + t * v.x + 0.5 ) % 1 - 0.5 )
This will yield three sawtooth plots whose periods depend on the components of the direction vector (e.g. if the direction vector is (1, 0, 0), the x-plot will vary linearly between 0 and 0.5, with a period of 1, while the other plots will remain constant at whatever p0 is.
You need to find the first value of t for which all three plots are below some threshold level, determined by the size of your primitives. You can thus vastly reduce the number of t values to be checked by considering the plot with the longest (non-infinite) period first, before checking the higher-frequency plots.
I can't shake the feeling that it may be possible to compute the correct value of t based on the periods of the three plots, but I can't come up with anything that isn't scuppered by the starting position not being the origin, and the threshold value not being zero. :-/
Basically, what you'll need to do is to express the line in the form of a function. From there, you will just mathematically have to calculate if the ray intersects with each object, as and then if it does make sure you get the one it collides with closest to the source.
This isn't fast, so you will have to do a lot of optimization here. The most obvious thing is to use bounding boxes instead of the actual shapes. From there, you can do things like use Octrees or BSTs (Binary Space Partitioning).
Well, anyway, there might be something I am overlooking that becomes possible through the extra limitations you have to your system, but that is how I had to make a ray tracer for a course.
You state in the question that an iterative solution is unacceptably slow - I assume you mean iterative in the sense of testing every object in the grid against the line.
Iterate instead over the grid cubes that the line intersects, and for each cube test the 8 objects that the cube intersects. Look to Bresenham's line drawing algorithm for how to find which cubes the line intersects.
Note that Bresenham's will not return absolutely every cube that the ray intersects, but for finding which primitives to test I'm fairly sure that it'll be good enough.
It also has the nice properties:
Extremely simple - this will be handy if you're running it on the GPU
Returns results iteratively along the ray, so you can stop as soon as you find a hit.
Try this approach:
Determine the function of the ray;
Say the grid is divided in different planes in z axis, the ray will intersect with each 'z plane' (the plane where the grid nodes at the same height lie in), and you can easily compute the coordinate (x, y, z) of the intersect points from the ray function;
Swipe z planes, you can easily determine which intersect points lie in a cubic or a sphere;
But the ray may intersects with the cubics/spheres between the z planes, so you need to repeat the 1-3 steps in x, y axises. This will ensure no intersection is left off.
Throw out the repeated cubics/spheres found from x,y,z directions searches.
I'm struggling to find a rock solid solution to detecting collisions between a circle and a circle segment. Imagine a Field of View cone for a game enemy, with the circles representing objects of interest.
The diagram at the bottom is something I drew to try and work out some possible cases, but i'm sure there are more.
I understand how to quickly exlude extreme cases, I discard any targets that don't collide with the entire circle, and any cases where the center of the main circle is within the target circle are automatically true (E in the diagram).
I'm struggling to find a good way to check the rest of the cases. I've tried comparing distances between circle centers and the end points of the segments outer lines, and i've tried working out the angle of the center of the target circle from the center of the main circle and determining whether that is within the segment, but neither way seems to catch all cases.
Specifically it seems to go funky if the target circle is close to the center but not touching it (somewhere between E and B below), or if the segment is narrower than the target circle (so that the center is within the segment but both edges are outside it).
Is there a reliable method for doing this?
Extra info: The segment is described by position P, orientation O (whose magnitude is the circle radius), and a view size, S.
My most successful attempt to date involved determining the angles of the vectors ca1 and ca2, and checking if either of them lies between the angles of vectors a1 and a2. This works for some cases as explained above, but not situations where the target circle is larger than the segment.
Edit 2
After implementing the best suggestion from below, there is still a false positive which I am unsure how best to eliminate. See the pink diagram below. The circle in the lower right is reporting as colliding with the segment because it's bounds overlap both half spaces and the main circle.
Final Edit
After discovering another edge case (4th image), i've settled on an approach which combines the two top answers from below and seems to cover all bases. I'll describe it here for the sake of those who follow.
First exclude anything that fails a quick circle-to-circle test.
Then test for collision between the circle and the two outer lines of the segment. If it touches either, return true.
Finally, do a couple of point-to-halfspace tests using the center of the circle and the two outer lines (as described by Gareth below). If it passes both of those it's in, otherwise return false.
A. Check if it is intersecting the whole cirlce.
B. Check if it is intersecting either of the straight segment lines.
C. If not, check if the angle between the circle centres lies in the angular range of the segment (dot product is good for this).
Intersection requires A && (B || C)
A circular segment (with central angle less than 180°) is the intersection of three figures: a circle, and two half-planes:
So a figure intersects the circular segment only if it intersects all three of these figures. [That's only if but not if; see below.]
Circle/circle intersection is easy (compare the distance between their centres with the sum of their radii).
For circle/half-plane intersection, represent the half-plane in the form p · n ≤ k (where p is the point to be tested, n is a unit vector that's normal to the line defining the half-plane, and k is a constant). Then a circle with centre x and radius r intersects the half-plane if x · n ≤ k + r.
(If you need to handle a circular segment with central angle greater than 180°, split it into two segments with central angle less than 180°. If I understand your problem description correctly, you won't need to do this, since your field of view will always be less than 180°, but it's worth mentioning.)
Edited to add: as pointed out by beeglebug, a circle can intersect all three figures without intersecting their intersection. Oops. But I believe that this can only happen when the circle is behind the centre of the segment, as in the diagram below, and in this case we can apply the separating axis test for convex figures.
The separating axis theorem says that two convex figures fail to intersect if there exists a line such that one figure falls entirely on one side of the line, and the other figure on the other.
If any separating axis exists in this case, then the axis that's perpendicular to the line between the centre of the circle and the centre of the segment is a separating axis (as shown).
Let the centre of the segment be at the origin, let the circle have centre x and radius r, and let the two half-planes have (outward) normals n₁ and n₂. The circle is "behind" the segment if
x · n₁ > 0 and x · n₂ > 0
and the axis separates it from the segment if
|x| > r