diff --git a/crates/fj-core/src/algorithms/approx/cycle.rs b/crates/fj-core/src/algorithms/approx/cycle.rs index ad6d4e489..163a523e1 100644 --- a/crates/fj-core/src/algorithms/approx/cycle.rs +++ b/crates/fj-core/src/algorithms/approx/cycle.rs @@ -9,7 +9,7 @@ use fj_math::Segment; use crate::objects::{Cycle, Surface}; use super::{ - edge::{EdgeApprox, EdgeApproxCache}, + edge::{EdgeApproxCache, HalfEdgeApprox}, Approx, ApproxPoint, Tolerance, }; @@ -25,7 +25,7 @@ impl Approx for (&Cycle, &Surface) { let (cycle, surface) = self; let tolerance = tolerance.into(); - let edges = cycle + let half_edges = cycle .half_edges() .iter() .map(|edge| { @@ -33,15 +33,15 @@ impl Approx for (&Cycle, &Surface) { }) .collect(); - CycleApprox { edges } + CycleApprox { half_edges } } } /// An approximation of a [`Cycle`] #[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct CycleApprox { - /// The approximated edges that make up the approximated cycle - pub edges: Vec, + /// The approximated half-edges that make up the approximated cycle + pub half_edges: Vec, } impl CycleApprox { @@ -49,8 +49,8 @@ impl CycleApprox { pub fn points(&self) -> Vec> { let mut points = Vec::new(); - for approx in &self.edges { - points.extend(approx.points()); + for approx in &self.half_edges { + points.extend(approx.points.iter().copied()); } if let Some(point) = points.first() { diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index b4c05e8ec..b199c442b 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -23,7 +23,7 @@ use super::{ }; impl Approx for (&HalfEdge, &Surface) { - type Approximation = EdgeApprox; + type Approximation = HalfEdgeApprox; type Cache = EdgeApproxCache; fn approx_with_cache( @@ -92,43 +92,26 @@ impl Approx for (&HalfEdge, &Surface) { // immediately, and it will be there on the second iteration. }; - segment - .points - .inner - .into_iter() - .map(|point| { - let point_surface = - edge.path().point_from_path_coords(point.local_form); + segment.points.inner.into_iter().map(|point| { + let point_surface = + edge.path().point_from_path_coords(point.local_form); - ApproxPoint::new(point_surface, point.global_form) - }) - .collect() + ApproxPoint::new(point_surface, point.global_form) + }) }; - EdgeApprox { first, rest } + let mut points = vec![first]; + points.extend(rest); + + HalfEdgeApprox { points } } } /// An approximation of a [`HalfEdge`] #[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub struct EdgeApprox { - /// The point that approximates the first vertex of the edge - first: ApproxPoint<2>, - - /// The approximation of the rest of the edge - rest: Vec>, -} - -impl EdgeApprox { - /// Compute the points that approximate the edge - pub fn points(&self) -> Vec> { - let mut points = Vec::new(); - - points.push(self.first); - points.extend(self.rest.iter().cloned()); - - points - } +pub struct HalfEdgeApprox { + /// The points that approximate the half-edge + pub points: Vec>, } fn approx_curve( @@ -279,7 +262,11 @@ mod tests { let tolerance = 1.; let approx = (&edge, surface.deref()).approx(tolerance); - assert_eq!(approx.rest, Vec::new()); + let expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + assert_eq!(approx.points, expected_approx); } #[test] @@ -296,7 +283,11 @@ mod tests { let tolerance = 1.; let approx = (&edge, &surface).approx(tolerance); - assert_eq!(approx.rest, Vec::new()); + let expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + assert_eq!(approx.points, expected_approx); } #[test] @@ -319,18 +310,20 @@ mod tests { let tolerance = 1.; let approx = (&edge, &surface).approx(tolerance); - let expected_approx = (path, boundary) - .approx(tolerance) - .into_iter() - .map(|(point_local, _)| { - let point_surface = - edge.path().point_from_path_coords(point_local); - let point_global = - surface.geometry().point_from_surface_coords(point_surface); - ApproxPoint::new(point_surface, point_global) - }) - .collect::>(); - assert_eq!(approx.rest, expected_approx); + let mut expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + expected_approx.extend( + (path, boundary).approx(tolerance).into_iter().map( + |(point_local, _)| { + let point_surface = + edge.path().point_from_path_coords(point_local); + ApproxPoint::from_surface_point(point_surface, &surface) + }, + ), + ); + assert_eq!(approx.points, expected_approx); } #[test] @@ -343,17 +336,18 @@ mod tests { let tolerance = 1.; let approx = (&edge, surface.deref()).approx(tolerance); - let expected_approx = + let mut expected_approx = vec![{ + let point_surface = edge.start_position(); + ApproxPoint::from_surface_point(point_surface, &surface) + }]; + expected_approx.extend( (&edge.path(), CurveBoundary::from([[0.], [TAU]])) .approx(tolerance) .into_iter() .map(|(_, point_surface)| { - let point_global = surface - .geometry() - .point_from_surface_coords(point_surface); - ApproxPoint::new(point_surface, point_global) - }) - .collect::>(); - assert_eq!(approx.rest, expected_approx); + ApproxPoint::from_surface_point(point_surface, &surface) + }), + ); + assert_eq!(approx.points, expected_approx); } } diff --git a/crates/fj-core/src/algorithms/approx/mod.rs b/crates/fj-core/src/algorithms/approx/mod.rs index 72497ffb1..94564c89c 100644 --- a/crates/fj-core/src/algorithms/approx/mod.rs +++ b/crates/fj-core/src/algorithms/approx/mod.rs @@ -18,6 +18,8 @@ use std::{ use fj_math::Point; +use crate::objects::Surface; + pub use self::tolerance::{InvalidTolerance, Tolerance}; /// Approximate an object @@ -59,7 +61,7 @@ pub struct ApproxPoint { } impl ApproxPoint { - /// Create an instance of `ApproxPoint`, without a source + /// Create an instance of `ApproxPoint` pub fn new( local_form: impl Into>, global_form: impl Into>, @@ -71,6 +73,19 @@ impl ApproxPoint { } } +impl ApproxPoint<2> { + /// Create an instance of `ApproxPoint` from a surface point + pub fn from_surface_point( + point_surface: impl Into>, + surface: &Surface, + ) -> Self { + let point_surface = point_surface.into(); + let point_global = + surface.geometry().point_from_surface_coords(point_surface); + ApproxPoint::new(point_surface, point_global) + } +} + impl Eq for ApproxPoint {} impl PartialEq for ApproxPoint {