🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

3D Line Segment and Cubic Bezier Path Segment Intersection Advice

Started by
3 comments, last by Eleventy 6 years, 1 month ago

I am seeking advice regarding whether the following algorithm works (and if so, is the fastest) for a 3D line segment intersecting with a 3D cubic bezier curve:

To test for intersections of a 3D line segment with a 3D bezier cubic path segment, project the 3D cubic path segment and the 3D line segment along a plane coincident with the 3D line segment.  The chosen plane orientation should not cause the resultant 2D bezier cubic path segment to be linear unless its 3D counterpart is also linear.  By default, the orientation will be along the Y axis (a vertical plane perpendicular to the X-Z axis).

Then, perform a normal 2D bezier cubic curve/2D line intersection.  For each found T value in the 2D intersection, only keep the T values in the 3D counterpart curve having all three coordinate values that are intersected by the actual 3D line segment.

Eleventy

Advertisement

Your proposed method should work since a true intersection will show up no matter which plane you project the Bezier curve onto. 2D Bezier-line intersection can be pretty fast, so I think that might be a fast method. There also might be simpler intermediate checks you can do, like testing if the line intersects the convex hull of the Bezier curve (assuming you don't have negative weights if it's a rational curve).

Just for the sake of variety, an alternative method you could also do is compute a rough polyline of the curve, determine the maximum error between the tessellation and the curve (a fairly simple calculation), and define that as the radius of a cylinder wrapped around each line segment, and then do a line-cylinder intersection to see if it intersects. This is probably not the fastest method though.

Thanks!  Good to know that any projected plane will work with this method, and that it is fast - once I create the rest of the 3D counterparts to the 2D system I already have in place, I will implement this method.

Eleventy

So this method does indeed work, with some caveats:

The 3D -> 2D plane projection process can introduce a loss of precision and can cause false negatives in regards to line segments.

Example: If one has a 3D line segment starting at (2.5, 2.5, 0.0) and going to (5.0, 5.0, 0.0) which happens to hit a point along a Cubic bezier path segment that crosses (2.5, 2.5, 0.0) in the exact middle of the cubic path (T value of 0.5), one would expect a an intersection at (2.5, 2.5, 0.0) with a T value of 0.5 and a U value (representing the position along the line segment from the starting point) of 0.  However, the result ends up being something like (2.4999045..., 2.4999045..., 0.0) with a T value of 0.49995.. and U of -0.0001..  This value lies outside of the line segment (and is also beyond the tolerance of my epsilon-based floating point equality checking) and would not be considered an intersection.

A possible solution is to "snap" values close to U values of 0 to 1 within a large multiple of the binary double floating point precision epsilon (from my testing, the multiple that works is 1.0E10 - this like having values like 1.0E-6 equal to 0.0).

However, I cannot simply override the U value to lie within the line segment, as I would need a full solution that contains all valid fields.  In addition, I have to check that a point at this U is indeed on the Bezier curve.  I need the Bezier's T value for a point.

I take this "snapped" U value, find the corresponding point along the line segment (which should be very close to the initial (2.49.., 2.49.., 0.0) value - in this case (2.5, 2.5, 0)) and perform a Bezier closest-T to guessed T and Point Newtonian approximation method with the 0.4999.. T value to get the corresponding Bezier T value, which should now be at or very close to 0.5.  I then confirm equality with both points to ensure a collision within the line segment and bezier curve took place.

It seems like a lot for such a special case and it might be computationally inefficient, but it appears to work.

If anybody has any other ideas in regards to dealing with floating-point precision issues such as these, please let me know.

Eleventy

This topic is closed to new replies.

Advertisement