diff --git a/crates/fj-kernel/src/algorithms/intersection/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersection/curve_edge.rs index 22841cb67..177037ef2 100644 --- a/crates/fj-kernel/src/algorithms/intersection/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersection/curve_edge.rs @@ -1,10 +1,10 @@ use fj_math::{Point, Segment}; -use crate::objects::{CurveKind, Edge}; +use crate::objects::{Curve, CurveKind, Edge}; use super::LineSegmentIntersection; -/// The intersection between a curve and an [`Edge`], in curve coordinates +/// The intersection between a [`Curve`] and an [`Edge`], in curve coordinates #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub enum CurveEdgeIntersection { /// The curve and edge intersect at a point @@ -26,10 +26,10 @@ impl CurveEdgeIntersection { /// # Panics /// /// Currently, only intersections between lines and line segments can be - /// computed. Panics, if a different type of curve or [`Edge`] is + /// computed. Panics, if a different type of [`Curve`] or [`Edge`] is /// passed. - pub fn compute(curve: &CurveKind<2>, edge: &Edge) -> Option { - let curve_as_line = match curve { + pub fn compute(curve: &Curve, edge: &Edge) -> Option { + let curve_as_line = match curve.kind() { CurveKind::Line(line) => line, _ => todo!("Curve-edge intersection only supports lines"), }; @@ -87,7 +87,7 @@ mod tests { let edge = Edge::build() .line_segment_from_points(&surface, [[1., -1.], [1., 1.]]); - let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge); + let intersection = CurveEdgeIntersection::compute(&curve, &edge); assert_eq!( intersection, @@ -104,7 +104,7 @@ mod tests { let edge = Edge::build() .line_segment_from_points(&surface, [[-1., -1.], [-1., 1.]]); - let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge); + let intersection = CurveEdgeIntersection::compute(&curve, &edge); assert_eq!( intersection, @@ -121,7 +121,7 @@ mod tests { let edge = Edge::build() .line_segment_from_points(&surface, [[-1., -1.], [1., -1.]]); - let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge); + let intersection = CurveEdgeIntersection::compute(&curve, &edge); assert!(intersection.is_none()); } @@ -133,7 +133,7 @@ mod tests { let edge = Edge::build() .line_segment_from_points(&surface, [[-1., 0.], [1., 0.]]); - let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge); + let intersection = CurveEdgeIntersection::compute(&curve, &edge); assert_eq!( intersection, diff --git a/crates/fj-kernel/src/algorithms/intersection/curve_face.rs b/crates/fj-kernel/src/algorithms/intersection/curve_face.rs index 54f2117f4..cbbf730fe 100644 --- a/crates/fj-kernel/src/algorithms/intersection/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersection/curve_face.rs @@ -4,10 +4,10 @@ use fj_math::Point; use crate::{ algorithms::intersection::CurveEdgeIntersection, - objects::{CurveKind, Face}, + objects::{Curve, Face}, }; -/// The intersections between a curve and a [`Face`], in curve coordinates +/// The intersections between a [`Curve`] and a [`Face`], in curve coordinates #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct CurveFaceIntersectionList { intervals: Vec, @@ -27,8 +27,8 @@ impl CurveFaceIntersectionList { Self { intervals } } - /// Compute the intersections between a curve and a [`Face`] - pub fn compute(curve: &CurveKind<2>, face: &Face) -> Self { + /// Compute the intersections between a [`Curve`] and a [`Face`] + pub fn compute(curve: &Curve, face: &Face) -> Self { let edges = face.all_cycles().flat_map(|cycle| { let edges: Vec<_> = cycle.edges().cloned().collect(); edges @@ -140,18 +140,16 @@ pub type CurveFaceIntersection = [Point<1>; 2]; #[cfg(test)] mod tests { - use fj_math::{Line, Point, Vector}; - - use crate::objects::{CurveKind, Face, Surface}; + use crate::objects::{Curve, Face, Surface}; use super::CurveFaceIntersectionList; #[test] fn compute() { - let curve = CurveKind::Line(Line { - origin: Point::from([-3., 0.]), - direction: Vector::from([1., 0.]), - }); + let surface = Surface::xy_plane(); + + let curve = + Curve::build(surface).line_from_points([[-3., 0.], [-2., 0.]]); #[rustfmt::skip] let exterior = [ @@ -168,7 +166,6 @@ mod tests { [-1., 1.], ]; - let surface = Surface::xy_plane(); let face = Face::build(surface) .polygon_from_points(exterior) .with_hole(interior); diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index 46122ee73..48241de2f 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -1,31 +1,27 @@ use fj_math::{Line, Point, Scalar, Vector}; -use crate::objects::{CurveKind, Surface}; +use crate::objects::{Curve, CurveKind, GlobalCurve, Surface}; /// The intersection between two surfaces #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct SurfaceSurfaceIntersection { - /// The intersection curves, in the coordinates of the input surfaces - pub local_intersection_curves: [CurveKind<2>; 2], - - /// The intersection curve, in global coordinates - pub global_intersection_curve: CurveKind<3>, + /// The intersection curves + pub intersection_curves: [Curve; 2], } impl SurfaceSurfaceIntersection { /// Compute the intersection between two surfaces - pub fn compute(a: &Surface, b: &Surface) -> Option { + pub fn compute(surfaces: [&Surface; 2]) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes. // // Adaptations were made to get the intersection curves in local // coordinates for each surface. - let a_parametric = PlaneParametric::extract_from_surface(a); - let b_parametric = PlaneParametric::extract_from_surface(b); - - let a = PlaneConstantNormal::from_parametric_plane(&a_parametric); - let b = PlaneConstantNormal::from_parametric_plane(&b_parametric); + let planes_parametric = + surfaces.map(PlaneParametric::extract_from_surface); + let [a, b] = planes_parametric + .map(|plane| PlaneConstantNormal::from_parametric_plane(&plane)); let direction = a.normal.cross(&b.normal); @@ -48,18 +44,21 @@ impl SurfaceSurfaceIntersection { let line = Line { origin, direction }; - let curve_a = project_line_into_plane(&line, &a_parametric); - let curve_b = project_line_into_plane(&line, &b_parametric); - let curve_global = CurveKind::Line(Line { origin, direction }); + let curves = planes_parametric.map(|plane| { + let local = project_line_into_plane(&line, &plane); + let global = CurveKind::Line(Line { origin, direction }); + + Curve::new(local, GlobalCurve::from_kind(global)) + }); Some(Self { - local_intersection_curves: [curve_a, curve_b], - global_intersection_curve: curve_global, + intersection_curves: curves, }) } } /// A plane in parametric form +#[derive(Clone, Copy)] struct PlaneParametric { pub origin: Point<3>, pub u: Vector<3>, @@ -154,12 +153,12 @@ mod tests { let xz = Surface::xz_plane(); // Coincident and parallel planes don't have an intersection curve. - assert_eq!(SurfaceSurfaceIntersection::compute(&xy, &xy), None); + assert_eq!(SurfaceSurfaceIntersection::compute([&xy, &xy]), None); assert_eq!( - SurfaceSurfaceIntersection::compute( + SurfaceSurfaceIntersection::compute([ &xy, &xy.transform(&Transform::translation([0., 0., 1.])) - ), + ]), None, ); @@ -167,13 +166,9 @@ mod tests { let expected_xz = Curve::build(xz).u_axis(); assert_eq!( - SurfaceSurfaceIntersection::compute(&xy, &xz), + SurfaceSurfaceIntersection::compute([&xy, &xz]), Some(SurfaceSurfaceIntersection { - local_intersection_curves: [ - *expected_xy.kind(), - *expected_xz.kind() - ], - global_intersection_curve: *expected_xy.global().kind(), + intersection_curves: [expected_xy, expected_xz], }) ); }