diff --git a/crates/fj-core/src/algorithms/approx/curve/approx.rs b/crates/fj-core/src/algorithms/approx/curve/approx.rs index 4f1bbc047..b0ee82d3f 100644 --- a/crates/fj-core/src/algorithms/approx/curve/approx.rs +++ b/crates/fj-core/src/algorithms/approx/curve/approx.rs @@ -1,5 +1,3 @@ -use std::collections::VecDeque; - use fj_math::Point; use crate::geometry::{CurveBoundaries, CurveBoundary}; @@ -38,40 +36,9 @@ impl CurveApprox { &mut self, new_segment: CurveApproxSegment, ) -> CurveApproxSegment { - let mut overlapping_segments = VecDeque::new(); - - let mut i = 0; - loop { - let Some((boundary, _)) = self.segments.inner.get(i) else { - break; - }; - - if boundary.overlaps(&new_segment.boundary) { - let segment = self.segments.inner.swap_remove(i); - overlapping_segments.push_back(segment); - continue; - } - - i += 1; - } - - let mut merged_boundary = new_segment.boundary; - let mut merged_segment = new_segment.points; - - for (boundary, segment) in overlapping_segments { - assert!( - merged_boundary.overlaps(&boundary), - "Shouldn't merge segments that don't overlap." - ); - - merged_boundary = merged_boundary.union(boundary); - merged_segment.merge(&segment, boundary); - } - - self.segments - .inner - .push((merged_boundary, merged_segment.clone())); - self.segments.inner.sort(); + let (merged_boundary, merged_segment) = self + .segments + .merge(new_segment.boundary, new_segment.points); CurveApproxSegment { boundary: merged_boundary, diff --git a/crates/fj-core/src/algorithms/approx/curve/points.rs b/crates/fj-core/src/algorithms/approx/curve/points.rs index 631803fde..ee0fbc56a 100644 --- a/crates/fj-core/src/algorithms/approx/curve/points.rs +++ b/crates/fj-core/src/algorithms/approx/curve/points.rs @@ -56,4 +56,8 @@ impl CurveBoundariesPayload for CurveApproxPoints { fn make_subset(&mut self, boundary: CurveBoundary>) { self.make_subset(boundary) } + + fn merge(&mut self, other: &Self, other_boundary: CurveBoundary>) { + self.merge(other, other_boundary) + } } diff --git a/crates/fj-core/src/geometry/boundary/multiple.rs b/crates/fj-core/src/geometry/boundary/multiple.rs index 5ef26469a..b4516e3b7 100644 --- a/crates/fj-core/src/geometry/boundary/multiple.rs +++ b/crates/fj-core/src/geometry/boundary/multiple.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + use fj_math::Point; use crate::geometry::CurveBoundary; @@ -61,6 +63,50 @@ impl CurveBoundaries { self.inner.retain(|(boundary, _)| !boundary.is_empty()); } + + /// Merge the provided boundary into `self` + /// + /// Return the merged boundary and payload. + pub fn merge( + &mut self, + new_boundary: CurveBoundary>, + new_payload: T, + ) -> (CurveBoundary>, T) { + let mut overlapping_payloads = VecDeque::new(); + + let mut i = 0; + loop { + let Some((boundary, _)) = self.inner.get(i) else { + break; + }; + + if boundary.overlaps(&new_boundary) { + let payload = self.inner.swap_remove(i); + overlapping_payloads.push_back(payload); + continue; + } + + i += 1; + } + + let mut merged_boundary = new_boundary; + let mut merged_payload = new_payload; + + for (boundary, payload) in overlapping_payloads { + assert!( + merged_boundary.overlaps(&boundary), + "Shouldn't merge boundaries that don't overlap." + ); + + merged_boundary = merged_boundary.union(boundary); + merged_payload.merge(&payload, boundary); + } + + self.inner.push((merged_boundary, merged_payload.clone())); + self.inner.sort(); + + (merged_boundary, merged_payload) + } } impl Default for CurveBoundaries { @@ -76,9 +122,13 @@ pub trait CurveBoundariesPayload: Clone + Ord { /// Reduce the payload to the subset defined by the provided boundary fn make_subset(&mut self, boundary: CurveBoundary>); + + /// Merge the provided payload + fn merge(&mut self, other: &Self, other_boundary: CurveBoundary>); } impl CurveBoundariesPayload for () { fn reverse(&mut self) {} fn make_subset(&mut self, _: CurveBoundary>) {} + fn merge(&mut self, _: &Self, _: CurveBoundary>) {} }