diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index b80419791..481dca730 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -1,5 +1,6 @@ //! Curve approximation +mod cache; mod segment; -pub use self::segment::CurveApproxSegment; +pub use self::{cache::CurveApproxCache, segment::CurveApproxSegment}; diff --git a/crates/fj-core/src/algorithms/approx/curve/cache.rs b/crates/fj-core/src/algorithms/approx/curve/cache.rs new file mode 100644 index 000000000..d10e3bada --- /dev/null +++ b/crates/fj-core/src/algorithms/approx/curve/cache.rs @@ -0,0 +1,53 @@ +use std::collections::BTreeMap; + +use fj_math::Point; + +use crate::{ + geometry::CurveBoundary, + objects::Curve, + storage::{Handle, HandleWrapper}, +}; + +use super::CurveApproxSegment; + +/// Cache for curve approximations +#[derive(Default)] +pub struct CurveApproxCache { + inner: BTreeMap< + (HandleWrapper, CurveBoundary>), + CurveApproxSegment, + >, +} + +impl CurveApproxCache { + /// Get an approximation from the cache + pub fn get( + &self, + curve: &Handle, + boundary: &CurveBoundary>, + ) -> Option { + if let Some(approx) = self.inner.get(&(curve.clone().into(), *boundary)) + { + return Some(approx.clone()); + } + if let Some(approx) = + self.inner.get(&(curve.clone().into(), boundary.reverse())) + { + // If we have a cache entry for the reverse boundary, we need to use + // that too! + return Some(approx.clone().reverse()); + } + + None + } + + /// Insert an approximated segment of the curve into the cache + pub fn insert( + &mut self, + curve: Handle, + new_segment: CurveApproxSegment, + ) -> Option { + self.inner + .insert((curve.into(), new_segment.boundary), new_segment) + } +} diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index aa7d6bc6d..599de8e93 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -15,7 +15,10 @@ use crate::{ storage::{Handle, HandleWrapper}, }; -use super::{curve::CurveApproxSegment, Approx, ApproxPoint, Tolerance}; +use super::{ + curve::{CurveApproxCache, CurveApproxSegment}, + Approx, ApproxPoint, Tolerance, +}; impl Approx for (&Edge, &Surface) { type Approximation = EdgeApprox; @@ -86,17 +89,13 @@ impl Approx for (&Edge, &Surface) { let approx = match cached_approx { Some(approx) => approx, None => { - let approx = approx_edge( + let approx = approx_curve( &edge.path(), surface, edge.boundary(), tolerance, ); - cache.insert_curve_approx( - edge.curve().clone(), - edge.boundary(), - approx, - ) + cache.insert_curve_approx(edge.curve().clone(), approx) } }; @@ -138,7 +137,7 @@ impl EdgeApprox { } } -fn approx_edge( +fn approx_curve( path: &SurfacePath, surface: &Surface, boundary: CurveBoundary>, @@ -218,18 +217,10 @@ fn approx_edge( #[derive(Default)] pub struct EdgeApproxCache { start_position_approx: BTreeMap, Point<3>>, - curve_approx: BTreeMap< - (HandleWrapper, CurveBoundary>), - CurveApproxSegment, - >, + curve_approx: CurveApproxCache, } impl EdgeApproxCache { - /// Create an empty cache - pub fn new() -> Self { - Self::default() - } - fn get_start_position_approx( &self, handle: &Handle, @@ -254,30 +245,16 @@ impl EdgeApproxCache { handle: Handle, boundary: CurveBoundary>, ) -> Option { - if let Some(approx) = - self.curve_approx.get(&(handle.clone().into(), boundary)) - { - return Some(approx.clone()); - } - if let Some(approx) = - self.curve_approx.get(&(handle.into(), boundary.reverse())) - { - // If we have a cache entry for the reverse boundary, we need to use - // that too! - return Some(approx.clone().reverse()); - } - - None + self.curve_approx.get(&handle, &boundary) } fn insert_curve_approx( &mut self, handle: Handle, - boundary: CurveBoundary>, approx: CurveApproxSegment, ) -> CurveApproxSegment { self.curve_approx - .insert((handle.into(), boundary), approx.clone()) + .insert(handle, approx.clone()) .unwrap_or(approx) } }