diff --git a/crates/fj-core/src/algorithms/approx/cycle.rs b/crates/fj-core/src/algorithms/approx/cycle.rs index 04c3eadad..9ada80137 100644 --- a/crates/fj-core/src/algorithms/approx/cycle.rs +++ b/crates/fj-core/src/algorithms/approx/cycle.rs @@ -9,13 +9,13 @@ use fj_math::Segment; use crate::objects::{Cycle, Surface}; use super::{ - edge::{EdgeApprox, EdgeCache}, + edge::{EdgeApprox, EdgeApproxCache}, Approx, ApproxPoint, Tolerance, }; impl Approx for (&Cycle, &Surface) { type Approximation = CycleApprox; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index d3df2f9a2..aa7d6bc6d 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -19,7 +19,7 @@ use super::{curve::CurveApproxSegment, Approx, ApproxPoint, Tolerance}; impl Approx for (&Edge, &Surface) { type Approximation = EdgeApprox; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, @@ -28,20 +28,24 @@ impl Approx for (&Edge, &Surface) { ) -> Self::Approximation { let (edge, surface) = self; - let position_surface = edge.start_position(); - let position_global = match cache.get_position(edge.start_vertex()) { - Some(position) => position, - None => { - let position_global = surface - .geometry() - .point_from_surface_coords(position_surface); - cache.insert_position(edge.start_vertex(), position_global) - } - }; + let start_position_surface = edge.start_position(); + let start_position = + match cache.get_start_position_approx(edge.start_vertex()) { + Some(position) => position, + None => { + let position_global = surface + .geometry() + .point_from_surface_coords(start_position_surface); + cache.insert_start_position_approx( + edge.start_vertex(), + position_global, + ) + } + }; - let first = ApproxPoint::new(position_surface, position_global); + let first = ApproxPoint::new(start_position_surface, start_position); - let points = { + let rest = { // We cache approximated `Edge`s using the `Curve`s they reference // and their boundary on that curve as the key. That bakes in the // undesirable assumption that all coincident `Edge`s are also @@ -78,7 +82,7 @@ impl Approx for (&Edge, &Surface) { // able to deliver partial results for a given boundary, then // generating (and caching) the rest of it on the fly. let cached_approx = - cache.get_edge(edge.curve().clone(), edge.boundary()); + cache.get_curve_approx(edge.curve().clone(), edge.boundary()); let approx = match cached_approx { Some(approx) => approx, None => { @@ -88,7 +92,7 @@ impl Approx for (&Edge, &Surface) { edge.boundary(), tolerance, ); - cache.insert_edge( + cache.insert_curve_approx( edge.curve().clone(), edge.boundary(), approx, @@ -108,7 +112,7 @@ impl Approx for (&Edge, &Surface) { .collect() }; - EdgeApprox { first, points } + EdgeApprox { first, rest } } } @@ -116,10 +120,10 @@ impl Approx for (&Edge, &Surface) { #[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct EdgeApprox { /// The point that approximates the first vertex of the edge - pub first: ApproxPoint<2>, + first: ApproxPoint<2>, - /// The approximation of the edge - pub points: Vec>, + /// The approximation of the rest of the edge + rest: Vec>, } impl EdgeApprox { @@ -128,7 +132,7 @@ impl EdgeApprox { let mut points = Vec::new(); points.push(self.first.clone()); - points.extend(self.points.iter().cloned()); + points.extend(self.rest.iter().cloned()); points } @@ -210,35 +214,53 @@ fn approx_edge( CurveApproxSegment { boundary, points } } -/// A cache for results of an approximation +/// Cache for edge approximations #[derive(Default)] -pub struct EdgeCache { - edge_approx: BTreeMap< +pub struct EdgeApproxCache { + start_position_approx: BTreeMap, Point<3>>, + curve_approx: BTreeMap< (HandleWrapper, CurveBoundary>), CurveApproxSegment, >, - vertex_approx: BTreeMap, Point<3>>, } -impl EdgeCache { +impl EdgeApproxCache { /// Create an empty cache pub fn new() -> Self { Self::default() } - /// Access the approximation for the given edge, if available - fn get_edge( + fn get_start_position_approx( + &self, + handle: &Handle, + ) -> Option> { + self.start_position_approx + .get(&handle.clone().into()) + .cloned() + } + + fn insert_start_position_approx( + &mut self, + handle: &Handle, + position: Point<3>, + ) -> Point<3> { + self.start_position_approx + .insert(handle.clone().into(), position) + .unwrap_or(position) + } + + fn get_curve_approx( &self, handle: Handle, boundary: CurveBoundary>, ) -> Option { if let Some(approx) = - self.edge_approx.get(&(handle.clone().into(), boundary)) + self.curve_approx.get(&(handle.clone().into(), boundary)) { return Some(approx.clone()); } if let Some(approx) = - self.edge_approx.get(&(handle.into(), boundary.reverse())) + self.curve_approx.get(&(handle.into(), boundary.reverse())) { // If we have a cache entry for the reverse boundary, we need to use // that too! @@ -248,31 +270,16 @@ impl EdgeCache { None } - /// Insert the approximation of an edge - fn insert_edge( + fn insert_curve_approx( &mut self, handle: Handle, boundary: CurveBoundary>, approx: CurveApproxSegment, ) -> CurveApproxSegment { - self.edge_approx + self.curve_approx .insert((handle.into(), boundary), approx.clone()) .unwrap_or(approx) } - - fn get_position(&self, handle: &Handle) -> Option> { - self.vertex_approx.get(&handle.clone().into()).cloned() - } - - fn insert_position( - &mut self, - handle: &Handle, - position: Point<3>, - ) -> Point<3> { - self.vertex_approx - .insert(handle.clone().into(), position) - .unwrap_or(position) - } } #[cfg(test)] @@ -300,7 +307,7 @@ mod tests { let tolerance = 1.; let approx = (&edge, surface.deref()).approx(tolerance); - assert_eq!(approx.points, Vec::new()); + assert_eq!(approx.rest, Vec::new()); } #[test] @@ -317,7 +324,7 @@ mod tests { let tolerance = 1.; let approx = (&edge, &surface).approx(tolerance); - assert_eq!(approx.points, Vec::new()); + assert_eq!(approx.rest, Vec::new()); } #[test] @@ -351,7 +358,7 @@ mod tests { ApproxPoint::new(point_surface, point_global) }) .collect::>(); - assert_eq!(approx.points, expected_approx); + assert_eq!(approx.rest, expected_approx); } #[test] @@ -375,6 +382,6 @@ mod tests { ApproxPoint::new(point_surface, point_global) }) .collect::>(); - assert_eq!(approx.points, expected_approx); + assert_eq!(approx.rest, expected_approx); } } diff --git a/crates/fj-core/src/algorithms/approx/face.rs b/crates/fj-core/src/algorithms/approx/face.rs index 261c0d7eb..40e70717f 100644 --- a/crates/fj-core/src/algorithms/approx/face.rs +++ b/crates/fj-core/src/algorithms/approx/face.rs @@ -12,12 +12,12 @@ use crate::{ }; use super::{ - cycle::CycleApprox, edge::EdgeCache, Approx, ApproxPoint, Tolerance, + cycle::CycleApprox, edge::EdgeApproxCache, Approx, ApproxPoint, Tolerance, }; impl Approx for &FaceSet { type Approximation = BTreeSet; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, @@ -63,7 +63,7 @@ impl Approx for &FaceSet { impl Approx for &Face { type Approximation = FaceApprox; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, diff --git a/crates/fj-core/src/algorithms/approx/shell.rs b/crates/fj-core/src/algorithms/approx/shell.rs index 0b9e3601d..1fbb21121 100644 --- a/crates/fj-core/src/algorithms/approx/shell.rs +++ b/crates/fj-core/src/algorithms/approx/shell.rs @@ -4,11 +4,11 @@ use std::collections::BTreeSet; use crate::objects::Shell; -use super::{edge::EdgeCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Shell { type Approximation = BTreeSet; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, diff --git a/crates/fj-core/src/algorithms/approx/sketch.rs b/crates/fj-core/src/algorithms/approx/sketch.rs index 7748fb92a..2e935a9f6 100644 --- a/crates/fj-core/src/algorithms/approx/sketch.rs +++ b/crates/fj-core/src/algorithms/approx/sketch.rs @@ -4,11 +4,11 @@ use std::collections::BTreeSet; use crate::objects::Sketch; -use super::{edge::EdgeCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Sketch { type Approximation = BTreeSet; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self, diff --git a/crates/fj-core/src/algorithms/approx/solid.rs b/crates/fj-core/src/algorithms/approx/solid.rs index 4aff45ecb..8fae93993 100644 --- a/crates/fj-core/src/algorithms/approx/solid.rs +++ b/crates/fj-core/src/algorithms/approx/solid.rs @@ -4,11 +4,11 @@ use std::collections::BTreeSet; use crate::objects::Solid; -use super::{edge::EdgeCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Solid { type Approximation = BTreeSet; - type Cache = EdgeCache; + type Cache = EdgeApproxCache; fn approx_with_cache( self,