use fj_math::{Point, Segment};
use crate::{geometry::curve::Curve, objects::HalfEdge};
use super::LineSegmentIntersection;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum CurveEdgeIntersection {
Point {
point_on_curve: Point<1>,
},
Coincident {
points_on_curve: [Point<1>; 2],
},
}
impl CurveEdgeIntersection {
pub fn compute(curve: &Curve, half_edge: &HalfEdge) -> Option<Self> {
let curve_as_line = match curve {
Curve::Line(line) => line,
_ => todo!("Curve-edge intersection only supports lines"),
};
let edge_as_segment = {
let edge_curve_as_line = match half_edge.curve() {
Curve::Line(line) => line,
_ => {
todo!("Curve-edge intersection only supports line segments")
}
};
let edge_vertices = half_edge
.boundary()
.map(|point| edge_curve_as_line.point_from_line_coords(point));
Segment::from_points(edge_vertices)
};
let intersection =
LineSegmentIntersection::compute(curve_as_line, &edge_as_segment)?;
let intersection = match intersection {
LineSegmentIntersection::Point { point_on_line } => Self::Point {
point_on_curve: point_on_line,
},
LineSegmentIntersection::Coincident { points_on_line } => {
Self::Coincident {
points_on_curve: points_on_line,
}
}
};
Some(intersection)
}
}
#[cfg(test)]
mod tests {
use fj_math::Point;
use crate::{
geometry::curve::Curve, objects::HalfEdge, operations::BuildHalfEdge,
services::Services,
};
use super::CurveEdgeIntersection;
#[test]
fn compute_edge_in_front_of_curve_origin() {
let mut services = Services::new();
let curve = Curve::u_axis();
let half_edge = HalfEdge::line_segment(
[[1., -1.], [1., 1.]],
None,
&mut services.objects,
);
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
assert_eq!(
intersection,
Some(CurveEdgeIntersection::Point {
point_on_curve: Point::from([1.])
})
);
}
#[test]
fn compute_edge_behind_curve_origin() {
let mut services = Services::new();
let curve = Curve::u_axis();
let half_edge = HalfEdge::line_segment(
[[-1., -1.], [-1., 1.]],
None,
&mut services.objects,
);
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
assert_eq!(
intersection,
Some(CurveEdgeIntersection::Point {
point_on_curve: Point::from([-1.])
})
);
}
#[test]
fn compute_edge_parallel_to_curve() {
let mut services = Services::new();
let curve = Curve::u_axis();
let half_edge = HalfEdge::line_segment(
[[-1., -1.], [1., -1.]],
None,
&mut services.objects,
);
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
assert!(intersection.is_none());
}
#[test]
fn compute_edge_on_curve() {
let mut services = Services::new();
let curve = Curve::u_axis();
let half_edge = HalfEdge::line_segment(
[[-1., 0.], [1., 0.]],
None,
&mut services.objects,
);
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
assert_eq!(
intersection,
Some(CurveEdgeIntersection::Coincident {
points_on_curve: [Point::from([-1.]), Point::from([1.]),]
})
);
}
}