add intersection_ray_cubic_bezier_2d() function
@@ -17,6 +17,7 @@ from ezdxf.math import (
close_vectors,
cubic_bezier_bbox,
quadratic_bezier_bbox,
+ intersection_ray_cubic_bezier_2d,
)
@@ -223,3 +224,40 @@ class TestBezierCurveBoundingBox:
curve = Bezier3P([(0, 0), (1, 1), (2, 0)])
bbox = quadratic_bezier_bbox(curve)
assert bbox.extmax.y == pytest.approx(0.5)
+
+
+class TestRayCubicBezierCurve2dIntersection:
+ @pytest.fixture(scope="class")
+ def curve(self):
+ return Bezier4P([(0, -2), (2, 6), (4, -6), (6, 2)])
+
+ def test_no_intersection(self, curve):
+ assert (
+ len(intersection_ray_cubic_bezier_2d((0, -6), (1, -6), curve)) == 0
+ )
+
+ def test_one_intersection_point(self, curve):
+ points = intersection_ray_cubic_bezier_2d((3, -6), (3, 6), curve)
+ assert len(points) == 1
+ assert points[0].isclose((3, 0))
+
+ def test_two_intersection_points(self, curve):
+ points = intersection_ray_cubic_bezier_2d(
+ (-1.4, -2.5), (7.1, 3.9), curve
+ )
+ assert len(points) == 2
+ expected = (
+ (0.18851028511733303, -1.3039451970881237),
+ (2.5249135145844264, 0.4552289992165126),
+ )
+ assert all(p.isclose(e) for e, p in zip(expected, points)) is True
+
+ def test_three_intersection_points(self, curve):
+ points = intersection_ray_cubic_bezier_2d((0, 0), (1, 0), curve)
+ assert len(points) == 3
+ expected = (
+ (0.6762099922755492, 0.0),
+ (3.0, 0.0),
+ (5.323790007724451, 0.0),
+ )
+ assert all(p.isclose(e) for e, p in zip(expected, points)) is True
