From edaa961379926ab13033b923a6f65887adeaf46a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:10:25 +0200 Subject: [PATCH 01/18] Fix word in comment --- crates/fj-core/src/algorithms/approx/edge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 3246c735f..3faa8329e 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -1,7 +1,7 @@ //! Edge approximation //! //! The approximation of a curve is its first vertex, combined with the -//! approximation of its curve. The second vertex is left off, as edge +//! approximation of its curve. The second vertex is left out, as edge //! approximations are usually used to build cycle approximations, and this way, //! the caller doesn't have to deal with duplicate vertices. From 4b1614a6180dd43f96cefa43670f4a8c702fed91 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:15:31 +0200 Subject: [PATCH 02/18] Add `VertexApproxCache` --- crates/fj-core/src/algorithms/approx/edge.rs | 12 +++---- crates/fj-core/src/algorithms/approx/mod.rs | 1 + .../fj-core/src/algorithms/approx/vertex.rs | 34 +++++++++++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 crates/fj-core/src/algorithms/approx/vertex.rs diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 3faa8329e..bab4c0049 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -15,7 +15,7 @@ use crate::{ storage::{Handle, HandleWrapper}, }; -use super::{Approx, ApproxPoint, Tolerance}; +use super::{vertex::VertexApproxCache, Approx, ApproxPoint, Tolerance}; impl Approx for (&HalfEdge, &Surface) { type Approximation = HalfEdgeApprox; @@ -170,7 +170,7 @@ fn approx_curve( /// Cache for edge approximations #[derive(Default)] pub struct EdgeApproxCache { - start_position_approx: BTreeMap, Point<3>>, + start_position_approx: VertexApproxCache, curve_approx: BTreeMap< (HandleWrapper, CurveBoundary>), Vec>, @@ -182,9 +182,7 @@ impl EdgeApproxCache { &self, handle: &Handle, ) -> Option> { - self.start_position_approx - .get(&handle.clone().into()) - .cloned() + self.start_position_approx.get(handle) } fn insert_start_position_approx( @@ -192,9 +190,7 @@ impl EdgeApproxCache { handle: &Handle, position: Point<3>, ) -> Point<3> { - self.start_position_approx - .insert(handle.clone().into(), position) - .unwrap_or(position) + self.start_position_approx.insert(handle.clone(), position) } fn get_curve_approx( diff --git a/crates/fj-core/src/algorithms/approx/mod.rs b/crates/fj-core/src/algorithms/approx/mod.rs index 54e195469..521974d54 100644 --- a/crates/fj-core/src/algorithms/approx/mod.rs +++ b/crates/fj-core/src/algorithms/approx/mod.rs @@ -8,6 +8,7 @@ pub mod shell; pub mod sketch; pub mod solid; pub mod tolerance; +pub mod vertex; use std::{ cmp::Ordering, diff --git a/crates/fj-core/src/algorithms/approx/vertex.rs b/crates/fj-core/src/algorithms/approx/vertex.rs new file mode 100644 index 000000000..fbfde07c8 --- /dev/null +++ b/crates/fj-core/src/algorithms/approx/vertex.rs @@ -0,0 +1,34 @@ +//! Vertex approximation + +use std::collections::BTreeMap; + +use fj_math::Point; + +use crate::{ + objects::Vertex, + storage::{Handle, HandleWrapper}, +}; + +/// Cache for vertex approximations +#[derive(Default)] +pub struct VertexApproxCache { + inner: BTreeMap, Point<3>>, +} + +impl VertexApproxCache { + /// Get an approximated vertex from the cache + pub fn get(&self, handle: &Handle) -> Option> { + self.inner.get(&handle.clone().into()).cloned() + } + + /// Insert an approximated vertex into the cache + pub fn insert( + &mut self, + handle: Handle, + position: Point<3>, + ) -> Point<3> { + self.inner + .insert(handle.clone().into(), position) + .unwrap_or(position) + } +} From 93f72fcd4b6fcabe1051d9460eb372cde4504462 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:16:05 +0200 Subject: [PATCH 03/18] Simplify struct field name --- crates/fj-core/src/algorithms/approx/edge.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index bab4c0049..3d8bea0b7 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -170,7 +170,7 @@ fn approx_curve( /// Cache for edge approximations #[derive(Default)] pub struct EdgeApproxCache { - start_position_approx: VertexApproxCache, + start_position: VertexApproxCache, curve_approx: BTreeMap< (HandleWrapper, CurveBoundary>), Vec>, @@ -182,7 +182,7 @@ impl EdgeApproxCache { &self, handle: &Handle, ) -> Option> { - self.start_position_approx.get(handle) + self.start_position.get(handle) } fn insert_start_position_approx( @@ -190,7 +190,7 @@ impl EdgeApproxCache { handle: &Handle, position: Point<3>, ) -> Point<3> { - self.start_position_approx.insert(handle.clone(), position) + self.start_position.insert(handle.clone(), position) } fn get_curve_approx( From 6fd4cb292a1d9c810d32da2d6aaa782479763b0f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:17:19 +0200 Subject: [PATCH 04/18] Inline redundant method --- crates/fj-core/src/algorithms/approx/edge.rs | 33 ++++++++------------ 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 3d8bea0b7..1ce9837bf 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -30,19 +30,19 @@ impl Approx for (&HalfEdge, &Surface) { let tolerance = tolerance.into(); 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 start_position = match cache.start_position.get(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(start_position_surface, start_position); @@ -178,13 +178,6 @@ pub struct EdgeApproxCache { } impl EdgeApproxCache { - fn get_start_position_approx( - &self, - handle: &Handle, - ) -> Option> { - self.start_position.get(handle) - } - fn insert_start_position_approx( &mut self, handle: &Handle, From 31a621d0d807807f3d00677c72ce8a16f03dc18b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:18:26 +0200 Subject: [PATCH 05/18] Inline redundant method --- crates/fj-core/src/algorithms/approx/edge.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 1ce9837bf..c99c8f3b7 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -11,7 +11,7 @@ use fj_math::Point; use crate::{ geometry::{CurveBoundary, GlobalPath, SurfacePath}, - objects::{Curve, HalfEdge, Surface, Vertex}, + objects::{Curve, HalfEdge, Surface}, storage::{Handle, HandleWrapper}, }; @@ -37,10 +37,9 @@ impl Approx for (&HalfEdge, &Surface) { let position_global = surface .geometry() .point_from_surface_coords(start_position_surface); - cache.insert_start_position_approx( - edge.start_vertex(), - position_global, - ) + cache + .start_position + .insert(edge.start_vertex().clone(), position_global) } }; @@ -178,14 +177,6 @@ pub struct EdgeApproxCache { } impl EdgeApproxCache { - fn insert_start_position_approx( - &mut self, - handle: &Handle, - position: Point<3>, - ) -> Point<3> { - self.start_position.insert(handle.clone(), position) - } - fn get_curve_approx( &self, handle: Handle, From 9254fd8d0eb902876305de9c9d3d0c862c85dc15 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:25:23 +0200 Subject: [PATCH 06/18] Add `CurveApproxCache` --- crates/fj-core/src/algorithms/approx/curve.rs | 58 +++++++++++++++++++ crates/fj-core/src/algorithms/approx/edge.rs | 34 +++-------- crates/fj-core/src/algorithms/approx/mod.rs | 1 + 3 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 crates/fj-core/src/algorithms/approx/curve.rs diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs new file mode 100644 index 000000000..4ef95c84b --- /dev/null +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -0,0 +1,58 @@ +//! Curve approximation + +use std::collections::BTreeMap; + +use fj_math::Point; + +use crate::{ + geometry::CurveBoundary, + objects::Curve, + storage::{Handle, HandleWrapper}, +}; + +use super::ApproxPoint; + +/// Cache for curve approximations +#[derive(Default)] +pub struct CurveApproxCache { + inner: BTreeMap< + (HandleWrapper, CurveBoundary>), + Vec>, + >, +} + +impl CurveApproxCache { + /// Get an approximated curve from the cache + pub fn get( + &self, + handle: &Handle, + boundary: CurveBoundary>, + ) -> Option>> { + let handle = HandleWrapper::from(handle.clone()); + + if let Some(approx) = self.inner.get(&(handle.clone(), boundary)) { + return Some(approx.clone()); + } + if let Some(approx) = self.inner.get(&(handle, boundary.reverse())) { + let mut approx = approx.clone(); + approx.reverse(); + + return Some(approx); + } + + None + } + + /// Insert an approximated curve into the cache + pub fn insert( + &mut self, + handle: Handle, + boundary: CurveBoundary>, + approx: Vec>, + ) -> Vec> { + let handle = HandleWrapper::from(handle); + self.inner + .insert((handle, boundary), approx.clone()) + .unwrap_or(approx) + } +} diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index c99c8f3b7..96238b16c 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -5,17 +5,18 @@ //! approximations are usually used to build cycle approximations, and this way, //! the caller doesn't have to deal with duplicate vertices. -use std::collections::BTreeMap; - use fj_math::Point; use crate::{ geometry::{CurveBoundary, GlobalPath, SurfacePath}, objects::{Curve, HalfEdge, Surface}, - storage::{Handle, HandleWrapper}, + storage::Handle, }; -use super::{vertex::VertexApproxCache, Approx, ApproxPoint, Tolerance}; +use super::{ + curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint, + Tolerance, +}; impl Approx for (&HalfEdge, &Surface) { type Approximation = HalfEdgeApprox; @@ -170,10 +171,7 @@ fn approx_curve( #[derive(Default)] pub struct EdgeApproxCache { start_position: VertexApproxCache, - curve_approx: BTreeMap< - (HandleWrapper, CurveBoundary>), - Vec>, - >, + curve_approx: CurveApproxCache, } impl EdgeApproxCache { @@ -182,22 +180,7 @@ impl EdgeApproxCache { handle: Handle, boundary: CurveBoundary>, ) -> Option>> { - let curve = HandleWrapper::from(handle); - - if let Some(approx) = self.curve_approx.get(&(curve.clone(), boundary)) - { - return Some(approx.clone()); - } - if let Some(approx) = - self.curve_approx.get(&(curve, boundary.reverse())) - { - let mut approx = approx.clone(); - approx.reverse(); - - return Some(approx); - } - - None + self.curve_approx.get(&handle, boundary) } fn insert_curve_approx( @@ -206,8 +189,7 @@ impl EdgeApproxCache { boundary: CurveBoundary>, approx: Vec>, ) { - let curve = HandleWrapper::from(handle); - self.curve_approx.insert((curve, boundary), approx); + self.curve_approx.insert(handle, boundary, approx); } } diff --git a/crates/fj-core/src/algorithms/approx/mod.rs b/crates/fj-core/src/algorithms/approx/mod.rs index 521974d54..513763c59 100644 --- a/crates/fj-core/src/algorithms/approx/mod.rs +++ b/crates/fj-core/src/algorithms/approx/mod.rs @@ -1,5 +1,6 @@ //! Approximation of objects +pub mod curve; pub mod cycle; pub mod edge; pub mod face; From 00b0aef19734355539de2a7e284a8f2ed8c27781 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:25:43 +0200 Subject: [PATCH 07/18] Simplify struct field name --- crates/fj-core/src/algorithms/approx/edge.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 96238b16c..203b24004 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -171,7 +171,7 @@ fn approx_curve( #[derive(Default)] pub struct EdgeApproxCache { start_position: VertexApproxCache, - curve_approx: CurveApproxCache, + curve: CurveApproxCache, } impl EdgeApproxCache { @@ -180,7 +180,7 @@ impl EdgeApproxCache { handle: Handle, boundary: CurveBoundary>, ) -> Option>> { - self.curve_approx.get(&handle, boundary) + self.curve.get(&handle, boundary) } fn insert_curve_approx( @@ -189,7 +189,7 @@ impl EdgeApproxCache { boundary: CurveBoundary>, approx: Vec>, ) { - self.curve_approx.insert(handle, boundary, approx); + self.curve.insert(handle, boundary, approx); } } From 9d152e6ba07bcbc737e3908a4eed1f176b60ed0a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:26:22 +0200 Subject: [PATCH 08/18] Inline redundant method --- crates/fj-core/src/algorithms/approx/edge.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 203b24004..0eb9377d6 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -48,7 +48,7 @@ impl Approx for (&HalfEdge, &Surface) { let rest = { let cached = - cache.get_curve_approx(edge.curve().clone(), edge.boundary()); + cache.curve.get(&edge.curve().clone(), edge.boundary()); let approx = match cached { Some(approx) => approx, @@ -175,14 +175,6 @@ pub struct EdgeApproxCache { } impl EdgeApproxCache { - fn get_curve_approx( - &self, - handle: Handle, - boundary: CurveBoundary>, - ) -> Option>> { - self.curve.get(&handle, boundary) - } - fn insert_curve_approx( &mut self, handle: Handle, From 1b2b7408e1beca56e4f4b4036fadfc47b6e951ab Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:27:39 +0200 Subject: [PATCH 09/18] Inline redundant method --- crates/fj-core/src/algorithms/approx/edge.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 0eb9377d6..e8320f986 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -9,8 +9,7 @@ use fj_math::Point; use crate::{ geometry::{CurveBoundary, GlobalPath, SurfacePath}, - objects::{Curve, HalfEdge, Surface}, - storage::Handle, + objects::{HalfEdge, Surface}, }; use super::{ @@ -60,7 +59,7 @@ impl Approx for (&HalfEdge, &Surface) { tolerance, ); - cache.insert_curve_approx( + cache.curve.insert( edge.curve().clone(), edge.boundary(), approx.clone(), @@ -174,17 +173,6 @@ pub struct EdgeApproxCache { curve: CurveApproxCache, } -impl EdgeApproxCache { - fn insert_curve_approx( - &mut self, - handle: Handle, - boundary: CurveBoundary>, - approx: Vec>, - ) { - self.curve.insert(handle, boundary, approx); - } -} - #[cfg(test)] mod tests { use std::{f64::consts::TAU, ops::Deref}; From 659b6adf895c50496025d1ae1cc2d21e9f5d5fdd Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:30:33 +0200 Subject: [PATCH 10/18] Refactor to simplify --- crates/fj-core/src/algorithms/approx/edge.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index e8320f986..901dc997b 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -62,10 +62,8 @@ impl Approx for (&HalfEdge, &Surface) { cache.curve.insert( edge.curve().clone(), edge.boundary(), - approx.clone(), - ); - - approx + approx, + ) } }; From 9677d648ba3c4f9014e300d96d29a760806be2d2 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:34:26 +0200 Subject: [PATCH 11/18] Add `CurveApprox` --- crates/fj-core/src/algorithms/approx/curve.rs | 21 ++++++++++++------- crates/fj-core/src/algorithms/approx/edge.rs | 14 +++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 4ef95c84b..32550225f 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -12,13 +12,18 @@ use crate::{ use super::ApproxPoint; +/// Approximation of [`Curve`], within a specific boundary +#[derive(Clone)] +pub struct CurveApprox { + /// The points that approximate the curve within the boundary + pub points: Vec>, +} + /// Cache for curve approximations #[derive(Default)] pub struct CurveApproxCache { - inner: BTreeMap< - (HandleWrapper, CurveBoundary>), - Vec>, - >, + inner: + BTreeMap<(HandleWrapper, CurveBoundary>), CurveApprox>, } impl CurveApproxCache { @@ -27,7 +32,7 @@ impl CurveApproxCache { &self, handle: &Handle, boundary: CurveBoundary>, - ) -> Option>> { + ) -> Option { let handle = HandleWrapper::from(handle.clone()); if let Some(approx) = self.inner.get(&(handle.clone(), boundary)) { @@ -35,7 +40,7 @@ impl CurveApproxCache { } if let Some(approx) = self.inner.get(&(handle, boundary.reverse())) { let mut approx = approx.clone(); - approx.reverse(); + approx.points.reverse(); return Some(approx); } @@ -48,8 +53,8 @@ impl CurveApproxCache { &mut self, handle: Handle, boundary: CurveBoundary>, - approx: Vec>, - ) -> Vec> { + approx: CurveApprox, + ) -> CurveApprox { let handle = HandleWrapper::from(handle); self.inner .insert((handle, boundary), approx.clone()) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 901dc997b..b350bfeca 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -13,8 +13,9 @@ use crate::{ }; use super::{ - curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint, - Tolerance, + curve::{CurveApprox, CurveApproxCache}, + vertex::VertexApproxCache, + Approx, ApproxPoint, Tolerance, }; impl Approx for (&HalfEdge, &Surface) { @@ -67,7 +68,7 @@ impl Approx for (&HalfEdge, &Surface) { } }; - approx.into_iter().map(|point| { + approx.points.into_iter().map(|point| { let point_surface = edge.path().point_from_path_coords(point.local_form); @@ -94,7 +95,7 @@ fn approx_curve( surface: &Surface, boundary: CurveBoundary>, tolerance: impl Into, -) -> Vec> { +) -> CurveApprox { // There are different cases of varying complexity. Circles are the hard // part here, as they need to be approximated, while lines don't need to be. // @@ -156,12 +157,13 @@ fn approx_curve( } }; - points + let points = points .into_iter() .map(|(point_curve, point_global)| { ApproxPoint::new(point_curve, point_global) }) - .collect() + .collect(); + CurveApprox { points } } /// Cache for edge approximations From 88ee1b6e0287427fbaeab21ea3bb2eefdeafb8e6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:35:12 +0200 Subject: [PATCH 12/18] Add `CurveApprox::reverse` --- crates/fj-core/src/algorithms/approx/curve.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 32550225f..34eda002f 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -19,6 +19,13 @@ pub struct CurveApprox { pub points: Vec>, } +impl CurveApprox { + fn reverse(mut self) -> Self { + self.points.reverse(); + self + } +} + /// Cache for curve approximations #[derive(Default)] pub struct CurveApproxCache { @@ -39,10 +46,7 @@ impl CurveApproxCache { return Some(approx.clone()); } if let Some(approx) = self.inner.get(&(handle, boundary.reverse())) { - let mut approx = approx.clone(); - approx.points.reverse(); - - return Some(approx); + return Some(approx.clone().reverse()); } None From 527f9b32cd2264054906e9a0cdc23c387384b3c0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:37:15 +0200 Subject: [PATCH 13/18] Move `approx_curve` to `approx::curve` --- crates/fj-core/src/algorithms/approx/curve.rs | 82 +++++++++++++++++- crates/fj-core/src/algorithms/approx/edge.rs | 85 +------------------ 2 files changed, 81 insertions(+), 86 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 34eda002f..50b9c99f6 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -5,12 +5,88 @@ use std::collections::BTreeMap; use fj_math::Point; use crate::{ - geometry::CurveBoundary, - objects::Curve, + geometry::{CurveBoundary, GlobalPath, SurfacePath}, + objects::{Curve, Surface}, storage::{Handle, HandleWrapper}, }; -use super::ApproxPoint; +use super::{Approx, ApproxPoint, Tolerance}; + +pub(super) fn approx_curve( + path: &SurfacePath, + surface: &Surface, + boundary: CurveBoundary>, + tolerance: impl Into, +) -> CurveApprox { + // There are different cases of varying complexity. Circles are the hard + // part here, as they need to be approximated, while lines don't need to be. + // + // This will probably all be unified eventually, as `SurfacePath` and + // `GlobalPath` grow APIs that are better suited to implementing this code + // in a more abstract way. + let points = match (path, surface.geometry().u) { + (SurfacePath::Circle(_), GlobalPath::Circle(_)) => { + todo!( + "Approximating a circle on a curved surface not supported yet." + ) + } + (SurfacePath::Circle(_), GlobalPath::Line(_)) => { + (path, boundary) + .approx_with_cache(tolerance, &mut ()) + .into_iter() + .map(|(point_curve, point_surface)| { + // We're throwing away `point_surface` here, which is a bit + // weird, as we're recomputing it later (outside of this + // function). + // + // It should be fine though: + // + // 1. We're throwing this version away, so there's no danger + // of inconsistency between this and the later version. + // 2. This version should have been computed using the same + // path and parameters and the later version will be, so + // they should be the same anyway. + // 3. Not all other cases handled in this function have a + // surface point available, so it needs to be computed + // later anyway, in the general case. + + let point_global = surface + .geometry() + .point_from_surface_coords(point_surface); + (point_curve, point_global) + }) + .collect() + } + (SurfacePath::Line(line), _) => { + let range_u = + CurveBoundary::from(boundary.inner.map(|point_curve| { + [path.point_from_path_coords(point_curve).u] + })); + + let approx_u = (surface.geometry().u, range_u) + .approx_with_cache(tolerance, &mut ()); + + let mut points = Vec::new(); + for (u, _) in approx_u { + let t = (u.t - line.origin().u) / line.direction().u; + let point_surface = path.point_from_path_coords([t]); + let point_global = + surface.geometry().point_from_surface_coords(point_surface); + points.push((u, point_global)); + } + + points + } + }; + + let points = points + .into_iter() + .map(|(point_curve, point_global)| { + ApproxPoint::new(point_curve, point_global) + }) + .collect(); + CurveApprox { points } +} /// Approximation of [`Curve`], within a specific boundary #[derive(Clone)] diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index b350bfeca..0f5592543 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -5,15 +5,10 @@ //! approximations are usually used to build cycle approximations, and this way, //! the caller doesn't have to deal with duplicate vertices. -use fj_math::Point; - -use crate::{ - geometry::{CurveBoundary, GlobalPath, SurfacePath}, - objects::{HalfEdge, Surface}, -}; +use crate::objects::{HalfEdge, Surface}; use super::{ - curve::{CurveApprox, CurveApproxCache}, + curve::{approx_curve, CurveApproxCache}, vertex::VertexApproxCache, Approx, ApproxPoint, Tolerance, }; @@ -90,82 +85,6 @@ pub struct HalfEdgeApprox { pub points: Vec>, } -fn approx_curve( - path: &SurfacePath, - surface: &Surface, - boundary: CurveBoundary>, - tolerance: impl Into, -) -> CurveApprox { - // There are different cases of varying complexity. Circles are the hard - // part here, as they need to be approximated, while lines don't need to be. - // - // This will probably all be unified eventually, as `SurfacePath` and - // `GlobalPath` grow APIs that are better suited to implementing this code - // in a more abstract way. - let points = match (path, surface.geometry().u) { - (SurfacePath::Circle(_), GlobalPath::Circle(_)) => { - todo!( - "Approximating a circle on a curved surface not supported yet." - ) - } - (SurfacePath::Circle(_), GlobalPath::Line(_)) => { - (path, boundary) - .approx_with_cache(tolerance, &mut ()) - .into_iter() - .map(|(point_curve, point_surface)| { - // We're throwing away `point_surface` here, which is a bit - // weird, as we're recomputing it later (outside of this - // function). - // - // It should be fine though: - // - // 1. We're throwing this version away, so there's no danger - // of inconsistency between this and the later version. - // 2. This version should have been computed using the same - // path and parameters and the later version will be, so - // they should be the same anyway. - // 3. Not all other cases handled in this function have a - // surface point available, so it needs to be computed - // later anyway, in the general case. - - let point_global = surface - .geometry() - .point_from_surface_coords(point_surface); - (point_curve, point_global) - }) - .collect() - } - (SurfacePath::Line(line), _) => { - let range_u = - CurveBoundary::from(boundary.inner.map(|point_curve| { - [path.point_from_path_coords(point_curve).u] - })); - - let approx_u = (surface.geometry().u, range_u) - .approx_with_cache(tolerance, &mut ()); - - let mut points = Vec::new(); - for (u, _) in approx_u { - let t = (u.t - line.origin().u) / line.direction().u; - let point_surface = path.point_from_path_coords([t]); - let point_global = - surface.geometry().point_from_surface_coords(point_surface); - points.push((u, point_global)); - } - - points - } - }; - - let points = points - .into_iter() - .map(|(point_curve, point_global)| { - ApproxPoint::new(point_curve, point_global) - }) - .collect(); - CurveApprox { points } -} - /// Cache for edge approximations #[derive(Default)] pub struct EdgeApproxCache { From 49fbe36f1bb4f89ce0e13e25239421894b0bcb7f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:45:49 +0200 Subject: [PATCH 14/18] Add `Approx` implementation for curves --- crates/fj-core/src/algorithms/approx/curve.rs | 30 +++++++++++++++++++ crates/fj-core/src/algorithms/approx/edge.rs | 27 +++-------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index 50b9c99f6..a18871c3c 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -12,6 +12,36 @@ use crate::{ use super::{Approx, ApproxPoint, Tolerance}; +impl Approx + for ( + &Handle, + SurfacePath, + &Surface, + CurveBoundary>, + ) +{ + type Approximation = CurveApprox; + type Cache = CurveApproxCache; + + fn approx_with_cache( + self, + tolerance: impl Into, + cache: &mut Self::Cache, + ) -> Self::Approximation { + let (curve, surface_path, surface, boundary) = self; + + match cache.get(curve, boundary) { + Some(approx) => approx, + None => { + let approx = + approx_curve(&surface_path, surface, boundary, tolerance); + + cache.insert(curve.clone(), boundary, approx) + } + } + } +} + pub(super) fn approx_curve( path: &SurfacePath, surface: &Surface, diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 0f5592543..117713697 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -8,9 +8,8 @@ use crate::objects::{HalfEdge, Surface}; use super::{ - curve::{approx_curve, CurveApproxCache}, - vertex::VertexApproxCache, - Approx, ApproxPoint, Tolerance, + curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint, + Tolerance, }; impl Approx for (&HalfEdge, &Surface) { @@ -42,26 +41,8 @@ impl Approx for (&HalfEdge, &Surface) { let first = ApproxPoint::new(start_position_surface, start_position); let rest = { - let cached = - cache.curve.get(&edge.curve().clone(), edge.boundary()); - - let approx = match cached { - Some(approx) => approx, - None => { - let approx = approx_curve( - &edge.path(), - surface, - edge.boundary(), - tolerance, - ); - - cache.curve.insert( - edge.curve().clone(), - edge.boundary(), - approx, - ) - } - }; + let approx = (edge.curve(), edge.path(), surface, edge.boundary()) + .approx_with_cache(tolerance, &mut cache.curve); approx.points.into_iter().map(|point| { let point_surface = From 89c1e5d589970ec379b72d793fd408dc54bd67c9 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:46:12 +0200 Subject: [PATCH 15/18] Update struct name --- crates/fj-core/src/algorithms/approx/cycle.rs | 4 ++-- crates/fj-core/src/algorithms/approx/edge.rs | 4 ++-- crates/fj-core/src/algorithms/approx/face.rs | 7 ++++--- crates/fj-core/src/algorithms/approx/shell.rs | 4 ++-- crates/fj-core/src/algorithms/approx/sketch.rs | 4 ++-- crates/fj-core/src/algorithms/approx/solid.rs | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/cycle.rs b/crates/fj-core/src/algorithms/approx/cycle.rs index 163a523e1..091ff9cb8 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::{EdgeApproxCache, HalfEdgeApprox}, + edge::{HalfEdgeApprox, HalfEdgeApproxCache}, Approx, ApproxPoint, Tolerance, }; impl Approx for (&Cycle, &Surface) { type Approximation = CycleApprox; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; 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 117713697..bebf8bc85 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -14,7 +14,7 @@ use super::{ impl Approx for (&HalfEdge, &Surface) { type Approximation = HalfEdgeApprox; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; fn approx_with_cache( self, @@ -68,7 +68,7 @@ pub struct HalfEdgeApprox { /// Cache for edge approximations #[derive(Default)] -pub struct EdgeApproxCache { +pub struct HalfEdgeApproxCache { start_position: VertexApproxCache, curve: CurveApproxCache, } diff --git a/crates/fj-core/src/algorithms/approx/face.rs b/crates/fj-core/src/algorithms/approx/face.rs index 9df592ee6..aedccf6a5 100644 --- a/crates/fj-core/src/algorithms/approx/face.rs +++ b/crates/fj-core/src/algorithms/approx/face.rs @@ -12,12 +12,13 @@ use crate::{ }; use super::{ - cycle::CycleApprox, edge::EdgeApproxCache, Approx, ApproxPoint, Tolerance, + cycle::CycleApprox, edge::HalfEdgeApproxCache, Approx, ApproxPoint, + Tolerance, }; impl Approx for &Handles { type Approximation = BTreeSet; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; fn approx_with_cache( self, @@ -63,7 +64,7 @@ impl Approx for &Handles { impl Approx for &Face { type Approximation = FaceApprox; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; 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 1fbb21121..2a2fff755 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::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::HalfEdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Shell { type Approximation = BTreeSet; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; 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 2e935a9f6..1a49c0c95 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::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::HalfEdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Sketch { type Approximation = BTreeSet; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; 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 97ad09fc1..c24d0ed3f 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::EdgeApproxCache, face::FaceApprox, Approx, Tolerance}; +use super::{edge::HalfEdgeApproxCache, face::FaceApprox, Approx, Tolerance}; impl Approx for &Solid { type Approximation = BTreeSet; - type Cache = EdgeApproxCache; + type Cache = HalfEdgeApproxCache; fn approx_with_cache( self, From f7d9ff9f83ec4e4b6ab7baa57761ca0c0a9602a8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:46:29 +0200 Subject: [PATCH 16/18] Update doc comments --- crates/fj-core/src/algorithms/approx/edge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index bebf8bc85..a36433637 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -66,7 +66,7 @@ pub struct HalfEdgeApprox { pub points: Vec>, } -/// Cache for edge approximations +/// Cache for half-edge approximations #[derive(Default)] pub struct HalfEdgeApproxCache { start_position: VertexApproxCache, From 536050ea397c5de713d3bc367b16d5714fe11e81 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:46:52 +0200 Subject: [PATCH 17/18] Remove unnecessary `pub`s --- crates/fj-core/src/algorithms/approx/curve.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index a18871c3c..f2b6a362e 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -140,8 +140,7 @@ pub struct CurveApproxCache { } impl CurveApproxCache { - /// Get an approximated curve from the cache - pub fn get( + fn get( &self, handle: &Handle, boundary: CurveBoundary>, @@ -158,8 +157,7 @@ impl CurveApproxCache { None } - /// Insert an approximated curve into the cache - pub fn insert( + fn insert( &mut self, handle: Handle, boundary: CurveBoundary>, From 87a5856a91fd7c83a0dabb8f50f9a0175b334190 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 23 Oct 2023 13:49:54 +0200 Subject: [PATCH 18/18] Remove unnecessary `pub(super)` --- crates/fj-core/src/algorithms/approx/curve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index f2b6a362e..71d01d6ff 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -42,7 +42,7 @@ impl Approx } } -pub(super) fn approx_curve( +fn approx_curve( path: &SurfacePath, surface: &Surface, boundary: CurveBoundary>,