fj_kernel/algorithms/intersect/
curve_edge.rs1use fj_math::{Point, Segment};
2
3use crate::{geometry::curve::Curve, objects::HalfEdge};
4
5use super::LineSegmentIntersection;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
9pub enum CurveEdgeIntersection {
10 Point {
12 point_on_curve: Point<1>,
14 },
15
16 Coincident {
18 points_on_curve: [Point<1>; 2],
20 },
21}
22
23impl CurveEdgeIntersection {
24 pub fn compute(curve: &Curve, half_edge: &HalfEdge) -> Option<Self> {
32 let curve_as_line = match curve {
33 Curve::Line(line) => line,
34 _ => todo!("Curve-edge intersection only supports lines"),
35 };
36
37 let edge_as_segment = {
38 let edge_curve_as_line = match half_edge.curve() {
39 Curve::Line(line) => line,
40 _ => {
41 todo!("Curve-edge intersection only supports line segments")
42 }
43 };
44
45 let edge_vertices = half_edge
46 .boundary()
47 .map(|point| edge_curve_as_line.point_from_line_coords(point));
48
49 Segment::from_points(edge_vertices)
50 };
51
52 let intersection =
53 LineSegmentIntersection::compute(curve_as_line, &edge_as_segment)?;
54
55 let intersection = match intersection {
56 LineSegmentIntersection::Point { point_on_line } => Self::Point {
57 point_on_curve: point_on_line,
58 },
59 LineSegmentIntersection::Coincident { points_on_line } => {
60 Self::Coincident {
61 points_on_curve: points_on_line,
62 }
63 }
64 };
65
66 Some(intersection)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use fj_math::Point;
73
74 use crate::{
75 geometry::curve::Curve, objects::HalfEdge, operations::BuildHalfEdge,
76 services::Services,
77 };
78
79 use super::CurveEdgeIntersection;
80
81 #[test]
82 fn compute_edge_in_front_of_curve_origin() {
83 let mut services = Services::new();
84
85 let curve = Curve::u_axis();
86 let half_edge =
87 HalfEdge::line_segment([[1., -1.], [1., 1.]], None, &mut services);
88
89 let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
90
91 assert_eq!(
92 intersection,
93 Some(CurveEdgeIntersection::Point {
94 point_on_curve: Point::from([1.])
95 })
96 );
97 }
98
99 #[test]
100 fn compute_edge_behind_curve_origin() {
101 let mut services = Services::new();
102
103 let curve = Curve::u_axis();
104 let half_edge = HalfEdge::line_segment(
105 [[-1., -1.], [-1., 1.]],
106 None,
107 &mut services,
108 );
109
110 let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
111
112 assert_eq!(
113 intersection,
114 Some(CurveEdgeIntersection::Point {
115 point_on_curve: Point::from([-1.])
116 })
117 );
118 }
119
120 #[test]
121 fn compute_edge_parallel_to_curve() {
122 let mut services = Services::new();
123
124 let curve = Curve::u_axis();
125 let half_edge = HalfEdge::line_segment(
126 [[-1., -1.], [1., -1.]],
127 None,
128 &mut services,
129 );
130
131 let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
132
133 assert!(intersection.is_none());
134 }
135
136 #[test]
137 fn compute_edge_on_curve() {
138 let mut services = Services::new();
139
140 let curve = Curve::u_axis();
141 let half_edge =
142 HalfEdge::line_segment([[-1., 0.], [1., 0.]], None, &mut services);
143
144 let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
145
146 assert_eq!(
147 intersection,
148 Some(CurveEdgeIntersection::Coincident {
149 points_on_curve: [Point::from([-1.]), Point::from([1.]),]
150 })
151 );
152 }
153}