diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index bec4fa99f..337e08f13 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -1,13 +1,10 @@ use fj_math::{Point, Segment}; -use crate::{ - geometry::path::SurfacePath, - objects::{Curve, HalfEdge}, -}; +use crate::{geometry::path::SurfacePath, objects::HalfEdge}; use super::LineSegmentIntersection; -/// The intersection between a [`Curve`] and a [`HalfEdge`] +/// The intersection between a curve and a [`HalfEdge`] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub enum CurveEdgeIntersection { /// The curve and edge intersect at a point @@ -29,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 [`HalfEdge`] is + /// computed. Panics, if a different type of curve or [`HalfEdge`] is /// passed. - pub fn compute(curve: &Curve, half_edge: &HalfEdge) -> Option { - let curve_as_line = match curve.path() { + pub fn compute(curve: &SurfacePath, half_edge: &HalfEdge) -> Option { + let curve_as_line = match curve { SurfacePath::Line(line) => line, _ => todo!("Curve-edge intersection only supports lines"), }; @@ -53,7 +50,7 @@ impl CurveEdgeIntersection { }; let intersection = - LineSegmentIntersection::compute(&curve_as_line, &edge_as_segment)?; + LineSegmentIntersection::compute(curve_as_line, &edge_as_segment)?; let intersection = match intersection { LineSegmentIntersection::Point { point_on_line } => Self::Point { @@ -75,8 +72,9 @@ mod tests { use fj_math::Point; use crate::{ - builder::{CurveBuilder, HalfEdgeBuilder}, - partial::{PartialCurve, PartialHalfEdge, PartialObject}, + builder::HalfEdgeBuilder, + geometry::path::SurfacePath, + partial::{PartialHalfEdge, PartialObject}, services::Services, }; @@ -87,9 +85,7 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let mut curve = PartialCurve::default(); - curve.update_as_u_axis(); - let curve = curve.build(&mut services.objects); + let curve = SurfacePath::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); half_edge.update_as_line_segment_from_points([[1., -1.], [1., 1.]]); @@ -113,9 +109,7 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let mut curve = PartialCurve::default(); - curve.update_as_u_axis(); - let curve = curve.build(&mut services.objects); + let curve = SurfacePath::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); half_edge @@ -140,9 +134,7 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let mut curve = PartialCurve::default(); - curve.update_as_u_axis(); - let curve = curve.build(&mut services.objects); + let curve = SurfacePath::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); half_edge @@ -162,9 +154,7 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let mut curve = PartialCurve::default(); - curve.update_as_u_axis(); - let curve = curve.build(&mut services.objects); + let curve = SurfacePath::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); half_edge.update_as_line_segment_from_points([[-1., 0.], [1., 0.]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 386ec6de7..c6acad738 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -3,11 +3,11 @@ use std::vec; use fj_interop::ext::SliceExt; use fj_math::Point; -use crate::objects::{Curve, Face}; +use crate::{geometry::path::SurfacePath, objects::Face}; use super::CurveEdgeIntersection; -/// 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 CurveFaceIntersection { /// The intervals where the curve and face intersect, in curve coordinates @@ -27,8 +27,8 @@ impl CurveFaceIntersection { Self { intervals } } - /// Compute the intersections between a [`Curve`] and a [`Face`] - pub fn compute(curve: &Curve, face: &Face) -> Self { + /// Compute the intersection + pub fn compute(curve: &SurfacePath, face: &Face) -> Self { let half_edges = face.all_cycles().flat_map(|cycle| cycle.half_edges()); let mut intersections = Vec::new(); @@ -150,8 +150,9 @@ where #[cfg(test)] mod tests { use crate::{ - builder::{CurveBuilder, CycleBuilder, FaceBuilder}, - partial::{Partial, PartialCurve, PartialFace, PartialObject}, + builder::{CycleBuilder, FaceBuilder}, + geometry::path::SurfacePath, + partial::{Partial, PartialFace, PartialObject}, services::Services, }; @@ -161,9 +162,7 @@ mod tests { fn compute() { let mut services = Services::new(); - let mut curve = PartialCurve::default(); - curve.update_as_line_from_points([[-3., 0.], [-2., 0.]]); - let curve = curve.build(&mut services.objects); + let (curve, _) = SurfacePath::line_from_points([[-3., 0.], [-2., 0.]]); #[rustfmt::skip] let exterior = [ diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index 30b9b2460..96e2f35a8 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -1,11 +1,7 @@ use fj_interop::ext::ArrayExt; use iter_fixed::IntoIteratorFixed; -use crate::{ - objects::{Curve, Face, Objects}, - services::Service, - storage::Handle, -}; +use crate::{geometry::path::SurfacePath, objects::Face}; use super::{CurveFaceIntersection, SurfaceSurfaceIntersection}; @@ -18,7 +14,7 @@ pub struct FaceFaceIntersection { /// representation of the intersection on the respective face's surface. /// /// They both represent the same global curve. - pub intersection_curves: [Handle; 2], + pub intersection_curves: [SurfacePath; 2], /// The interval of this intersection, in curve coordinates /// @@ -28,14 +24,11 @@ pub struct FaceFaceIntersection { impl FaceFaceIntersection { /// Compute the intersections between two faces - pub fn compute( - faces: [&Face; 2], - objects: &mut Service, - ) -> Option { + pub fn compute(faces: [&Face; 2]) -> Option { let surfaces = faces.map(|face| face.surface().clone()); let intersection_curves = - match SurfaceSurfaceIntersection::compute(surfaces, objects) { + match SurfaceSurfaceIntersection::compute(surfaces) { Some(intersection) => intersection.intersection_curves, None => return None, }; @@ -69,9 +62,9 @@ mod tests { use crate::{ algorithms::intersect::CurveFaceIntersection, - builder::{CurveBuilder, CycleBuilder}, - insert::Insert, - partial::{Partial, PartialCurve, PartialFace, PartialObject}, + builder::CycleBuilder, + geometry::path::SurfacePath, + partial::{Partial, PartialFace, PartialObject}, services::Services, }; @@ -102,8 +95,7 @@ mod tests { face.build(&mut services.objects) }); - let intersection = - FaceFaceIntersection::compute([&a, &b], &mut services.objects); + let intersection = FaceFaceIntersection::compute([&a, &b]); assert!(intersection.is_none()); } @@ -133,15 +125,11 @@ mod tests { face.build(&mut services.objects) }); - let intersection = - FaceFaceIntersection::compute([&a, &b], &mut services.objects); + let intersection = FaceFaceIntersection::compute([&a, &b]); let expected_curves = surfaces.map(|_| { - let mut curve = PartialCurve::default(); - curve.update_as_line_from_points([[0., 0.], [1., 0.]]); - curve - .build(&mut services.objects) - .insert(&mut services.objects) + let (path, _) = SurfacePath::line_from_points([[0., 0.], [1., 0.]]); + path }); let expected_intervals = CurveFaceIntersection::from_intervals([[[-1.], [1.]]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs index 9406e92d4..b6927ff1f 100644 --- a/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersect/surface_surface.rs @@ -2,9 +2,7 @@ use fj_math::{Line, Plane, Point, Scalar}; use crate::{ geometry::path::{GlobalPath, SurfacePath}, - insert::Insert, - objects::{Curve, Objects, Surface}, - services::Service, + objects::Surface, storage::Handle, }; @@ -12,15 +10,12 @@ use crate::{ #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct SurfaceSurfaceIntersection { /// The intersection curves - pub intersection_curves: [Handle; 2], + pub intersection_curves: [SurfacePath; 2], } impl SurfaceSurfaceIntersection { /// Compute the intersection between two surfaces - pub fn compute( - surfaces: [Handle; 2], - objects: &mut Service, - ) -> Option { + pub fn compute(surfaces: [Handle; 2]) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes. // @@ -53,10 +48,8 @@ impl SurfaceSurfaceIntersection { let line = Line::from_origin_and_direction(origin, direction); - let curves = planes.map(|plane| { - let path = SurfacePath::Line(plane.project_line(&line)); - Curve::new(path).insert(objects) - }); + let curves = + planes.map(|plane| SurfacePath::Line(plane.project_line(&line))); Some(Self { intersection_curves: curves, @@ -83,10 +76,7 @@ mod tests { use pretty_assertions::assert_eq; use crate::{ - algorithms::transform::TransformObject, - builder::CurveBuilder, - insert::Insert, - partial::{PartialCurve, PartialObject}, + algorithms::transform::TransformObject, geometry::path::SurfacePath, services::Services, }; @@ -101,36 +91,21 @@ mod tests { // Coincident and parallel planes don't have an intersection curve. assert_eq!( - SurfaceSurfaceIntersection::compute( - [ - xy.clone(), - xy.clone().transform( - &Transform::translation([0., 0., 1.],), - &mut services.objects - ) - ], - &mut services.objects - ), + SurfaceSurfaceIntersection::compute([ + xy.clone(), + xy.clone().transform( + &Transform::translation([0., 0., 1.],), + &mut services.objects + ) + ],), None, ); - let mut expected_xy = PartialCurve::default(); - expected_xy.update_as_u_axis(); - let expected_xy = expected_xy - .build(&mut services.objects) - .insert(&mut services.objects); - - let mut expected_xz = PartialCurve::default(); - expected_xz.update_as_u_axis(); - let expected_xz = expected_xz - .build(&mut services.objects) - .insert(&mut services.objects); + let expected_xy = SurfacePath::u_axis(); + let expected_xz = SurfacePath::u_axis(); assert_eq!( - SurfaceSurfaceIntersection::compute( - [xy, xz], - &mut services.objects - ), + SurfaceSurfaceIntersection::compute([xy, xz],), Some(SurfaceSurfaceIntersection { intersection_curves: [expected_xy, expected_xz], }) diff --git a/crates/fj-kernel/src/builder/curve.rs b/crates/fj-kernel/src/builder/curve.rs index acc790cf1..19916b222 100644 --- a/crates/fj-kernel/src/builder/curve.rs +++ b/crates/fj-kernel/src/builder/curve.rs @@ -1,4 +1,4 @@ -use fj_math::{Point, Scalar, Vector}; +use fj_math::{Point, Scalar}; use crate::{geometry::path::SurfacePath, partial::PartialCurve}; @@ -50,17 +50,15 @@ pub trait CurveBuilder { impl CurveBuilder for PartialCurve { fn update_as_u_axis(&mut self) -> SurfacePath { - let a = Point::origin(); - let b = a + Vector::unit_u(); - - self.update_as_line_from_points([a, b]) + let path = SurfacePath::u_axis(); + self.path = Some(path.into()); + path } fn update_as_v_axis(&mut self) -> SurfacePath { - let a = Point::origin(); - let b = a + Vector::unit_v(); - - self.update_as_line_from_points([a, b]) + let path = SurfacePath::v_axis(); + self.path = Some(path.into()); + path } fn update_as_circle_from_radius( diff --git a/crates/fj-kernel/src/geometry/path.rs b/crates/fj-kernel/src/geometry/path.rs index cf85a2d73..e8866e0f9 100644 --- a/crates/fj-kernel/src/geometry/path.rs +++ b/crates/fj-kernel/src/geometry/path.rs @@ -43,6 +43,24 @@ impl SurfacePath { Self::Circle(Circle::from_center_and_radius(center, radius)) } + /// Build a line that represents the u-axis of the surface its on + pub fn u_axis() -> Self { + let a = Point::origin(); + let b = a + Vector::unit_u(); + + let (self_, _) = Self::line_from_points([a, b]); + self_ + } + + /// Build a line that represents the v-axis of the surface its on + pub fn v_axis() -> Self { + let a = Point::origin(); + let b = a + Vector::unit_v(); + + let (self_, _) = Self::line_from_points([a, b]); + self_ + } + /// Construct a line from two points /// /// Also returns the coordinates of the points on the path.