From bd0fc248928266b2cd9cbb94b057aa5863a1ad1b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 13 Feb 2024 10:21:48 +0100 Subject: [PATCH 1/4] Add `DeriveFrom` --- crates/fj-core/src/operations/derive.rs | 19 +++++++++++++++++++ crates/fj-core/src/operations/mod.rs | 1 + 2 files changed, 20 insertions(+) create mode 100644 crates/fj-core/src/operations/derive.rs diff --git a/crates/fj-core/src/operations/derive.rs b/crates/fj-core/src/operations/derive.rs new file mode 100644 index 0000000000..5063b214c1 --- /dev/null +++ b/crates/fj-core/src/operations/derive.rs @@ -0,0 +1,19 @@ +//! Mark a stored object as derived from another +//! +//! See [`DeriveFrom`]. + +use crate::{storage::Handle, Core}; + +/// Mark a store object as derived from another +pub trait DeriveFrom { + /// Mark this object as derived from the other object provided + fn derive_from(self, other: &Self, core: &mut Core) -> Self; +} + +impl DeriveFrom for Handle { + fn derive_from(self, _other: &Self, _core: &mut Core) -> Self { + // This is currently a no-op. Eventually, it will trigger a command to + // the layers that this information is relevant for. + self + } +} diff --git a/crates/fj-core/src/operations/mod.rs b/crates/fj-core/src/operations/mod.rs index fa138c719a..9645aa6edf 100644 --- a/crates/fj-core/src/operations/mod.rs +++ b/crates/fj-core/src/operations/mod.rs @@ -39,6 +39,7 @@ //! send a pull request! pub mod build; +pub mod derive; pub mod holes; pub mod insert; pub mod join; From 203937128b85cb4e488e6b88ce97d3104ea62d1c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Feb 2024 12:11:28 +0100 Subject: [PATCH 2/4] Rename variables to prepare for follow-on change --- .../fj-core/src/operations/replace/curve.rs | 44 ++++++++++----- .../src/operations/replace/half_edge.rs | 36 ++++++++----- .../fj-core/src/operations/replace/vertex.rs | 53 +++++++++++++------ 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/crates/fj-core/src/operations/replace/curve.rs b/crates/fj-core/src/operations/replace/curve.rs index 9ee37380a1..a62bb77486 100644 --- a/crates/fj-core/src/operations/replace/curve.rs +++ b/crates/fj-core/src/operations/replace/curve.rs @@ -52,9 +52,12 @@ impl ReplaceCurve for Cycle { let mut replacement_happened = false; let mut half_edges = Vec::new(); - for half_edge in self.half_edges() { - let half_edge = - half_edge.replace_curve(original, replacement.clone(), core); + for original_half_edge in self.half_edges() { + let half_edge = original_half_edge.replace_curve( + original, + replacement.clone(), + core, + ); replacement_happened |= half_edge.was_updated(); half_edges.push( half_edge @@ -86,9 +89,12 @@ impl ReplaceCurve for Region { replacement_happened |= exterior.was_updated(); let mut interiors = Vec::new(); - for cycle in self.interiors() { - let cycle = - cycle.replace_curve(original, replacement.clone(), core); + for original_cycle in self.interiors() { + let cycle = original_cycle.replace_curve( + original, + replacement.clone(), + core, + ); replacement_happened |= cycle.was_updated(); interiors.push( cycle @@ -121,9 +127,12 @@ impl ReplaceCurve for Sketch { let mut replacement_happened = false; let mut regions = Vec::new(); - for region in self.regions() { - let region = - region.replace_curve(original, replacement.clone(), core); + for original_region in self.regions() { + let region = original_region.replace_curve( + original, + replacement.clone(), + core, + ); replacement_happened |= region.was_updated(); regions.push( region @@ -172,8 +181,12 @@ impl ReplaceCurve for Shell { let mut replacement_happened = false; let mut faces = Vec::new(); - for face in self.faces() { - let face = face.replace_curve(original, replacement.clone(), core); + for original_face in self.faces() { + let face = original_face.replace_curve( + original, + replacement.clone(), + core, + ); replacement_happened |= face.was_updated(); faces.push( face.map_updated(|updated| updated.insert(core)) @@ -199,9 +212,12 @@ impl ReplaceCurve for Solid { let mut replacement_happened = false; let mut shells = Vec::new(); - for shell in self.shells() { - let shell = - shell.replace_curve(original, replacement.clone(), core); + for original_shell in self.shells() { + let shell = original_shell.replace_curve( + original, + replacement.clone(), + core, + ); replacement_happened |= shell.was_updated(); shells.push( shell diff --git a/crates/fj-core/src/operations/replace/half_edge.rs b/crates/fj-core/src/operations/replace/half_edge.rs index 6ab6ae3164..2f67280e1e 100644 --- a/crates/fj-core/src/operations/replace/half_edge.rs +++ b/crates/fj-core/src/operations/replace/half_edge.rs @@ -59,9 +59,12 @@ impl ReplaceHalfEdge for Region { replacement_happened |= exterior.was_updated(); let mut interiors = Vec::new(); - for cycle in self.interiors() { - let cycle = - cycle.replace_half_edge(original, replacements.clone(), core); + for original_cycle in self.interiors() { + let cycle = original_cycle.replace_half_edge( + original, + replacements.clone(), + core, + ); replacement_happened |= cycle.was_updated(); interiors.push( cycle @@ -94,9 +97,12 @@ impl ReplaceHalfEdge for Sketch { let mut replacement_happened = false; let mut regions = Vec::new(); - for region in self.regions() { - let region = - region.replace_half_edge(original, replacements.clone(), core); + for original_region in self.regions() { + let region = original_region.replace_half_edge( + original, + replacements.clone(), + core, + ); replacement_happened |= region.was_updated(); regions.push( region @@ -147,9 +153,12 @@ impl ReplaceHalfEdge for Shell { let mut replacement_happened = false; let mut faces = Vec::new(); - for face in self.faces() { - let face = - face.replace_half_edge(original, replacements.clone(), core); + for original_face in self.faces() { + let face = original_face.replace_half_edge( + original, + replacements.clone(), + core, + ); replacement_happened |= face.was_updated(); faces.push( face.map_updated(|updated| updated.insert(core)) @@ -175,9 +184,12 @@ impl ReplaceHalfEdge for Solid { let mut replacement_happened = false; let mut shells = Vec::new(); - for shell in self.shells() { - let shell = - shell.replace_half_edge(original, replacements.clone(), core); + for original_shell in self.shells() { + let shell = original_shell.replace_half_edge( + original, + replacements.clone(), + core, + ); replacement_happened |= shell.was_updated(); shells.push( shell diff --git a/crates/fj-core/src/operations/replace/vertex.rs b/crates/fj-core/src/operations/replace/vertex.rs index 968a743729..836169796c 100644 --- a/crates/fj-core/src/operations/replace/vertex.rs +++ b/crates/fj-core/src/operations/replace/vertex.rs @@ -54,9 +54,12 @@ impl ReplaceVertex for Cycle { let mut replacement_happened = false; let mut half_edges = Vec::new(); - for half_edge in self.half_edges() { - let half_edge = - half_edge.replace_vertex(original, replacement.clone(), core); + for original_half_edge in self.half_edges() { + let half_edge = original_half_edge.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= half_edge.was_updated(); half_edges.push( half_edge @@ -88,9 +91,12 @@ impl ReplaceVertex for Region { replacement_happened |= exterior.was_updated(); let mut interiors = Vec::new(); - for cycle in self.interiors() { - let cycle = - cycle.replace_vertex(original, replacement.clone(), core); + for original_cycle in self.interiors() { + let cycle = original_cycle.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= cycle.was_updated(); interiors.push( cycle @@ -123,9 +129,12 @@ impl ReplaceVertex for Sketch { let mut replacement_happened = false; let mut regions = Vec::new(); - for region in self.regions() { - let region = - region.replace_vertex(original, replacement.clone(), core); + for original_region in self.regions() { + let region = original_region.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= region.was_updated(); regions.push( region @@ -174,8 +183,12 @@ impl ReplaceVertex for Shell { let mut replacement_happened = false; let mut faces = Vec::new(); - for face in self.faces() { - let face = face.replace_vertex(original, replacement.clone(), core); + for original_face in self.faces() { + let face = original_face.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= face.was_updated(); faces.push( face.map_updated(|updated| updated.insert(core)) @@ -201,9 +214,12 @@ impl ReplaceVertex for Solid { let mut replacement_happened = false; let mut shells = Vec::new(); - for shell in self.shells() { - let shell = - shell.replace_vertex(original, replacement.clone(), core); + for original_shell in self.shells() { + let shell = original_shell.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= shell.was_updated(); shells.push( shell @@ -269,9 +285,12 @@ impl ReplaceVertex for Handle { let mut replacement_happened = false; let mut regions = Vec::new(); - for region in self.regions() { - let region = - region.replace_vertex(original, replacement.clone(), core); + for original_region in self.regions() { + let region = original_region.replace_vertex( + original, + replacement.clone(), + core, + ); replacement_happened |= region.was_updated(); regions.push( region From ad31e5f177e5e9c593dfb9b11cf76ab01a9a3f37 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Feb 2024 12:28:17 +0100 Subject: [PATCH 3/4] Rename variable to prepare for follow-up change --- crates/fj-core/src/operations/split/edge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/operations/split/edge.rs b/crates/fj-core/src/operations/split/edge.rs index f2b378839d..a812336794 100644 --- a/crates/fj-core/src/operations/split/edge.rs +++ b/crates/fj-core/src/operations/split/edge.rs @@ -42,7 +42,7 @@ impl SplitEdge for Shell { let [half_edge_a, half_edge_b] = half_edge .split_half_edge(point, core) - .map(|half_edge| half_edge.insert(core)); + .map(|half_edge_part| half_edge_part.insert(core)); let siblings = { let [sibling_a, sibling_b] = sibling.split_half_edge(point, core); From cb123b87ef553f12ce29ce50c83a1eb91b703207 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Feb 2024 12:53:47 +0100 Subject: [PATCH 4/4] Use `DeriveFrom` where appropriate This might not be all the places where it's needed, but I've been pretty careful about looking. If I forgot something, it might show up as a color being reset after an operation later. --- .../fj-core/src/operations/replace/curve.rs | 34 ++++++++++++----- .../src/operations/replace/half_edge.rs | 28 ++++++++++---- .../fj-core/src/operations/replace/vertex.rs | 38 ++++++++++++++----- .../fj-core/src/operations/reverse/cycle.rs | 7 +++- crates/fj-core/src/operations/reverse/face.rs | 20 ++++++++-- .../fj-core/src/operations/reverse/region.rs | 27 +++++++++---- crates/fj-core/src/operations/split/edge.rs | 12 ++++-- crates/fj-core/src/operations/split/face.rs | 23 ++++++++--- .../src/operations/sweep/shell_face.rs | 8 +++- crates/fj-core/src/operations/sweep/sketch.rs | 4 +- .../fj-core/src/operations/transform/mod.rs | 5 ++- crates/fj-core/src/operations/update/cycle.rs | 6 ++- crates/fj-core/src/operations/update/face.rs | 7 +++- .../src/operations/update/half_edge.rs | 10 +++-- .../fj-core/src/operations/update/region.rs | 10 +++-- crates/fj-core/src/operations/update/shell.rs | 6 ++- .../fj-core/src/operations/update/sketch.rs | 6 ++- crates/fj-core/src/operations/update/solid.rs | 6 ++- crates/fj-core/src/validate/face.rs | 8 +++- 19 files changed, 193 insertions(+), 72 deletions(-) diff --git a/crates/fj-core/src/operations/replace/curve.rs b/crates/fj-core/src/operations/replace/curve.rs index a62bb77486..fe6454ec68 100644 --- a/crates/fj-core/src/operations/replace/curve.rs +++ b/crates/fj-core/src/operations/replace/curve.rs @@ -4,7 +4,7 @@ use crate::{ objects::{ Curve, Cycle, Face, HalfEdge, IsObject, Region, Shell, Sketch, Solid, }, - operations::{insert::Insert, update::UpdateHalfEdge}, + operations::{derive::DeriveFrom, insert::Insert, update::UpdateHalfEdge}, storage::Handle, Core, }; @@ -61,7 +61,11 @@ impl ReplaceCurve for Cycle { replacement_happened |= half_edge.was_updated(); half_edges.push( half_edge - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated + .insert(core) + .derive_from(original_half_edge, core) + }) .into_inner(), ); } @@ -98,7 +102,9 @@ impl ReplaceCurve for Region { replacement_happened |= cycle.was_updated(); interiors.push( cycle - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_cycle, core) + }) .into_inner(), ); } @@ -106,7 +112,9 @@ impl ReplaceCurve for Region { if replacement_happened { ReplaceOutput::Updated(Region::new( exterior - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.exterior(), core) + }) .into_inner(), interiors, self.color(), @@ -136,7 +144,9 @@ impl ReplaceCurve for Sketch { replacement_happened |= region.was_updated(); regions.push( region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_region, core) + }) .into_inner(), ); } @@ -162,7 +172,9 @@ impl ReplaceCurve for Face { ReplaceOutput::Updated(Face::new( self.surface().clone(), region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.region(), core) + }) .into_inner(), )) } else { @@ -189,8 +201,10 @@ impl ReplaceCurve for Shell { ); replacement_happened |= face.was_updated(); faces.push( - face.map_updated(|updated| updated.insert(core)) - .into_inner(), + face.map_updated(|updated| { + updated.insert(core).derive_from(original_face, core) + }) + .into_inner(), ); } @@ -221,7 +235,9 @@ impl ReplaceCurve for Solid { replacement_happened |= shell.was_updated(); shells.push( shell - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_shell, core) + }) .into_inner(), ); } diff --git a/crates/fj-core/src/operations/replace/half_edge.rs b/crates/fj-core/src/operations/replace/half_edge.rs index 2f67280e1e..4142287e5c 100644 --- a/crates/fj-core/src/operations/replace/half_edge.rs +++ b/crates/fj-core/src/operations/replace/half_edge.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use crate::{ objects::{Cycle, Face, HalfEdge, IsObject, Region, Shell, Sketch, Solid}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -68,7 +68,9 @@ impl ReplaceHalfEdge for Region { replacement_happened |= cycle.was_updated(); interiors.push( cycle - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_cycle, core) + }) .into_inner(), ); } @@ -76,7 +78,9 @@ impl ReplaceHalfEdge for Region { if replacement_happened { ReplaceOutput::Updated(Region::new( exterior - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.exterior(), core) + }) .into_inner(), interiors, self.color(), @@ -106,7 +110,9 @@ impl ReplaceHalfEdge for Sketch { replacement_happened |= region.was_updated(); regions.push( region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_region, core) + }) .into_inner(), ); } @@ -134,7 +140,9 @@ impl ReplaceHalfEdge for Face { ReplaceOutput::Updated(Face::new( self.surface().clone(), region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.region(), core) + }) .into_inner(), )) } else { @@ -161,8 +169,10 @@ impl ReplaceHalfEdge for Shell { ); replacement_happened |= face.was_updated(); faces.push( - face.map_updated(|updated| updated.insert(core)) - .into_inner(), + face.map_updated(|updated| { + updated.insert(core).derive_from(original_face, core) + }) + .into_inner(), ); } @@ -193,7 +203,9 @@ impl ReplaceHalfEdge for Solid { replacement_happened |= shell.was_updated(); shells.push( shell - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_shell, core) + }) .into_inner(), ); } diff --git a/crates/fj-core/src/operations/replace/vertex.rs b/crates/fj-core/src/operations/replace/vertex.rs index 836169796c..48dd82952c 100644 --- a/crates/fj-core/src/operations/replace/vertex.rs +++ b/crates/fj-core/src/operations/replace/vertex.rs @@ -4,7 +4,7 @@ use crate::{ objects::{ Cycle, Face, HalfEdge, IsObject, Region, Shell, Sketch, Solid, Vertex, }, - operations::{insert::Insert, update::UpdateHalfEdge}, + operations::{derive::DeriveFrom, insert::Insert, update::UpdateHalfEdge}, storage::Handle, Core, }; @@ -63,7 +63,11 @@ impl ReplaceVertex for Cycle { replacement_happened |= half_edge.was_updated(); half_edges.push( half_edge - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated + .insert(core) + .derive_from(original_half_edge, core) + }) .into_inner(), ); } @@ -100,7 +104,9 @@ impl ReplaceVertex for Region { replacement_happened |= cycle.was_updated(); interiors.push( cycle - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_cycle, core) + }) .into_inner(), ); } @@ -108,7 +114,9 @@ impl ReplaceVertex for Region { if replacement_happened { ReplaceOutput::Updated(Region::new( exterior - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.exterior(), core) + }) .into_inner(), interiors, self.color(), @@ -138,7 +146,9 @@ impl ReplaceVertex for Sketch { replacement_happened |= region.was_updated(); regions.push( region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_region, core) + }) .into_inner(), ); } @@ -164,7 +174,9 @@ impl ReplaceVertex for Face { ReplaceOutput::Updated(Face::new( self.surface().clone(), region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(self.region(), core) + }) .into_inner(), )) } else { @@ -191,8 +203,10 @@ impl ReplaceVertex for Shell { ); replacement_happened |= face.was_updated(); faces.push( - face.map_updated(|updated| updated.insert(core)) - .into_inner(), + face.map_updated(|updated| { + updated.insert(core).derive_from(original_face, core) + }) + .into_inner(), ); } @@ -223,7 +237,9 @@ impl ReplaceVertex for Solid { replacement_happened |= shell.was_updated(); shells.push( shell - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_shell, core) + }) .into_inner(), ); } @@ -294,7 +310,9 @@ impl ReplaceVertex for Handle { replacement_happened |= region.was_updated(); regions.push( region - .map_updated(|updated| updated.insert(core)) + .map_updated(|updated| { + updated.insert(core).derive_from(original_region, core) + }) .into_inner(), ); } diff --git a/crates/fj-core/src/operations/reverse/cycle.rs b/crates/fj-core/src/operations/reverse/cycle.rs index 7332edc0f3..a8985ba680 100644 --- a/crates/fj-core/src/operations/reverse/cycle.rs +++ b/crates/fj-core/src/operations/reverse/cycle.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Cycle, HalfEdge}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, Core, }; @@ -19,6 +19,7 @@ impl Reverse for Cycle { next.start_vertex().clone(), ) .insert(core) + .derive_from(current, core) }) .collect::>(); @@ -31,7 +32,9 @@ impl Reverse for Cycle { impl ReverseCurveCoordinateSystems for Cycle { fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self { let edges = self.half_edges().iter().map(|edge| { - edge.reverse_curve_coordinate_systems(core).insert(core) + edge.reverse_curve_coordinate_systems(core) + .insert(core) + .derive_from(edge, core) }); Cycle::new(edges) diff --git a/crates/fj-core/src/operations/reverse/face.rs b/crates/fj-core/src/operations/reverse/face.rs index 7ec620ebc2..00508d0868 100644 --- a/crates/fj-core/src/operations/reverse/face.rs +++ b/crates/fj-core/src/operations/reverse/face.rs @@ -4,6 +4,7 @@ use crate::{ objects::Face, operations::{ build::Polygon, + derive::DeriveFrom, insert::{Insert, IsInsertedNo, IsInsertedYes}, }, Core, @@ -13,7 +14,11 @@ use super::{Reverse, ReverseCurveCoordinateSystems}; impl Reverse for Face { fn reverse(&self, core: &mut Core) -> Self { - let region = self.region().reverse(core).insert(core); + let region = self + .region() + .reverse(core) + .insert(core) + .derive_from(self.region(), core); Face::new(self.surface().clone(), region) } } @@ -28,7 +33,10 @@ impl Reverse for Polygon { impl Reverse for Polygon { fn reverse(&self, core: &mut Core) -> Self { let face: &Face = self.face.borrow(); - let face = face.reverse(core).insert(core); + let face = face + .reverse(core) + .insert(core) + .derive_from(&self.face, core); self.replace_face(face) } @@ -39,7 +47,8 @@ impl ReverseCurveCoordinateSystems for Face { let region = self .region() .reverse_curve_coordinate_systems(core) - .insert(core); + .insert(core) + .derive_from(self.region(), core); Face::new(self.surface().clone(), region) } } @@ -58,7 +67,10 @@ impl ReverseCurveCoordinateSystems { fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self { let face: &Face = self.face.borrow(); - let face = face.reverse_curve_coordinate_systems(core).insert(core); + let face = face + .reverse_curve_coordinate_systems(core) + .insert(core) + .derive_from(&self.face, core); self.replace_face(face) } diff --git a/crates/fj-core/src/operations/reverse/region.rs b/crates/fj-core/src/operations/reverse/region.rs index 8af95d882a..e90b8b799e 100644 --- a/crates/fj-core/src/operations/reverse/region.rs +++ b/crates/fj-core/src/operations/reverse/region.rs @@ -1,14 +1,21 @@ -use crate::{objects::Region, operations::insert::Insert, Core}; +use crate::{ + objects::Region, + operations::{derive::DeriveFrom, insert::Insert}, + Core, +}; use super::{Reverse, ReverseCurveCoordinateSystems}; impl Reverse for Region { fn reverse(&self, core: &mut Core) -> Self { - let exterior = self.exterior().reverse(core).insert(core); - let interiors = self - .interiors() - .iter() - .map(|cycle| cycle.reverse(core).insert(core)); + let exterior = self + .exterior() + .reverse(core) + .insert(core) + .derive_from(self.exterior(), core); + let interiors = self.interiors().iter().map(|cycle| { + cycle.reverse(core).insert(core).derive_from(cycle, core) + }); Region::new(exterior, interiors, self.color()) } @@ -19,9 +26,13 @@ impl ReverseCurveCoordinateSystems for Region { let exterior = self .exterior() .reverse_curve_coordinate_systems(core) - .insert(core); + .insert(core) + .derive_from(self.exterior(), core); let interiors = self.interiors().iter().map(|cycle| { - cycle.reverse_curve_coordinate_systems(core).insert(core) + cycle + .reverse_curve_coordinate_systems(core) + .insert(core) + .derive_from(cycle, core) }); Region::new(exterior, interiors, self.color()) diff --git a/crates/fj-core/src/operations/split/edge.rs b/crates/fj-core/src/operations/split/edge.rs index a812336794..2a74412d11 100644 --- a/crates/fj-core/src/operations/split/edge.rs +++ b/crates/fj-core/src/operations/split/edge.rs @@ -3,8 +3,8 @@ use fj_math::Point; use crate::{ objects::{HalfEdge, Shell}, operations::{ - insert::Insert, replace::ReplaceHalfEdge, split::SplitHalfEdge, - update::UpdateHalfEdge, + derive::DeriveFrom, insert::Insert, replace::ReplaceHalfEdge, + split::SplitHalfEdge, update::UpdateHalfEdge, }, queries::SiblingOfHalfEdge, storage::Handle, @@ -42,7 +42,9 @@ impl SplitEdge for Shell { let [half_edge_a, half_edge_b] = half_edge .split_half_edge(point, core) - .map(|half_edge_part| half_edge_part.insert(core)); + .map(|half_edge_part| { + half_edge_part.insert(core).derive_from(half_edge, core) + }); let siblings = { let [sibling_a, sibling_b] = sibling.split_half_edge(point, core); @@ -50,7 +52,9 @@ impl SplitEdge for Shell { |_, _| half_edge_b.start_vertex().clone(), core, ); - [sibling_a, sibling_b].map(|half_edge| half_edge.insert(core)) + [sibling_a, sibling_b].map(|half_edge| { + half_edge.insert(core).derive_from(&sibling, core) + }) }; let shell = self diff --git a/crates/fj-core/src/operations/split/face.rs b/crates/fj-core/src/operations/split/face.rs index f512e24a6a..ee1b93aa92 100644 --- a/crates/fj-core/src/operations/split/face.rs +++ b/crates/fj-core/src/operations/split/face.rs @@ -6,6 +6,7 @@ use crate::{ objects::{Face, HalfEdge, Shell}, operations::{ build::{BuildFace, BuildHalfEdge}, + derive::DeriveFrom, insert::Insert, presentation::SetColor, split::SplitEdge, @@ -145,17 +146,22 @@ impl SplitFace for Shell { }, core, ) - .insert(core); + .insert(core) + .derive_from(region, core); if let Some(color) = face.region().color() { - region = region.set_color(color).insert(core); + region = region + .set_color(color) + .insert(core) + .derive_from(®ion, core); } region }, core, ) - .insert(core); + .insert(core) + .derive_from(face, core); // The previous operation has moved the iterator along. let half_edges_of_face_starting_at_d = half_edges_of_face_starting_at_b; @@ -183,17 +189,22 @@ impl SplitFace for Shell { }, core, ) - .insert(core); + .insert(core) + .derive_from(region, core); if let Some(color) = face.region().color() { - region = region.set_color(color).insert(core); + region = region + .set_color(color) + .insert(core) + .derive_from(®ion, core); } region }, core, ) - .insert(core); + .insert(core) + .derive_from(face, core); let faces = [split_face_a, split_face_b]; let self_ = self_.update_face( diff --git a/crates/fj-core/src/operations/sweep/shell_face.rs b/crates/fj-core/src/operations/sweep/shell_face.rs index 3deb888cd6..6cace2c42b 100644 --- a/crates/fj-core/src/operations/sweep/shell_face.rs +++ b/crates/fj-core/src/operations/sweep/shell_face.rs @@ -3,6 +3,7 @@ use fj_math::Vector; use crate::{ objects::{Face, Region, Shell}, operations::{ + derive::DeriveFrom, insert::Insert, reverse::Reverse, sweep::{SweepCache, SweepRegion}, @@ -56,7 +57,12 @@ impl SweepFaceOfShell for Shell { let mut cache = SweepCache::default(); - let exterior = face.region().exterior().reverse(core).insert(core); + let exterior = face + .region() + .exterior() + .reverse(core) + .insert(core) + .derive_from(face.region().exterior(), core); let region = Region::new(exterior, [], face.region().color()); let faces = region .sweep_region(face.surface(), path, &mut cache, core) diff --git a/crates/fj-core/src/operations/sweep/sketch.rs b/crates/fj-core/src/operations/sweep/sketch.rs index 5e1a0e141a..320ccedd87 100644 --- a/crates/fj-core/src/operations/sweep/sketch.rs +++ b/crates/fj-core/src/operations/sweep/sketch.rs @@ -3,7 +3,7 @@ use fj_math::{Scalar, Vector}; use crate::{ geometry::GlobalPath, objects::{Face, Sketch, Solid, Surface}, - operations::{insert::Insert, reverse::Reverse}, + operations::{derive::DeriveFrom, insert::Insert, reverse::Reverse}, storage::Handle, Core, }; @@ -60,7 +60,7 @@ impl SweepSketch for Sketch { if is_negative_sweep { region.clone() } else { - region.reverse(core).insert(core) + region.reverse(core).insert(core).derive_from(region, core) } }; diff --git a/crates/fj-core/src/operations/transform/mod.rs b/crates/fj-core/src/operations/transform/mod.rs index b47b473f7d..538e00b688 100644 --- a/crates/fj-core/src/operations/transform/mod.rs +++ b/crates/fj-core/src/operations/transform/mod.rs @@ -21,6 +21,8 @@ use crate::{ Core, }; +use super::derive::DeriveFrom; + /// Transform an object /// /// # Implementation Note @@ -81,7 +83,8 @@ where let transformed = self .clone_object() .transform_with_cache(transform, core, cache) - .insert(core); + .insert(core) + .derive_from(self, core); cache.insert(self.clone(), transformed.clone()); diff --git a/crates/fj-core/src/operations/update/cycle.rs b/crates/fj-core/src/operations/update/cycle.rs index 3a56af1e04..1f672a424d 100644 --- a/crates/fj-core/src/operations/update/cycle.rs +++ b/crates/fj-core/src/operations/update/cycle.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Cycle, HalfEdge}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -64,7 +64,9 @@ impl UpdateCycle for Cycle { .half_edges() .replace( handle, - update(handle, core).map(|object| object.insert(core)), + update(handle, core).map(|object| { + object.insert(core).derive_from(handle, core) + }), ) .expect("Half-edge not found"); Cycle::new(edges) diff --git a/crates/fj-core/src/operations/update/face.rs b/crates/fj-core/src/operations/update/face.rs index 8df9dc624b..6c8303ff12 100644 --- a/crates/fj-core/src/operations/update/face.rs +++ b/crates/fj-core/src/operations/update/face.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Face, Region}, - operations::{build::Polygon, insert::Insert}, + operations::{build::Polygon, derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -28,7 +28,10 @@ impl UpdateFace for Face { T: Insert>, { let region = update(self.region(), core); - Face::new(self.surface().clone(), region.insert(core)) + Face::new( + self.surface().clone(), + region.insert(core).derive_from(self.region(), core), + ) } } diff --git a/crates/fj-core/src/operations/update/half_edge.rs b/crates/fj-core/src/operations/update/half_edge.rs index e04acbb6c1..ef7dbf9e9e 100644 --- a/crates/fj-core/src/operations/update/half_edge.rs +++ b/crates/fj-core/src/operations/update/half_edge.rs @@ -3,7 +3,7 @@ use fj_math::Point; use crate::{ geometry::{CurveBoundary, SurfacePath}, objects::{Curve, HalfEdge, Vertex}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -81,7 +81,9 @@ impl UpdateHalfEdge for HalfEdge { HalfEdge::new( self.path(), self.boundary(), - update(self.curve(), core).insert(core), + update(self.curve(), core) + .insert(core) + .derive_from(self.curve(), core), self.start_vertex().clone(), ) } @@ -98,7 +100,9 @@ impl UpdateHalfEdge for HalfEdge { self.path(), self.boundary(), self.curve().clone(), - update(self.start_vertex(), core).insert(core), + update(self.start_vertex(), core) + .insert(core) + .derive_from(self.start_vertex(), core), ) } } diff --git a/crates/fj-core/src/operations/update/region.rs b/crates/fj-core/src/operations/update/region.rs index adff50ef1b..cca4cd08b5 100644 --- a/crates/fj-core/src/operations/update/region.rs +++ b/crates/fj-core/src/operations/update/region.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Cycle, Region}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -54,7 +54,9 @@ impl UpdateRegion for Region { where T: Insert>, { - let exterior = update(self.exterior(), core).insert(core); + let exterior = update(self.exterior(), core) + .insert(core) + .derive_from(self.exterior(), core); Region::new(exterior, self.interiors().iter().cloned(), self.color()) } @@ -84,7 +86,9 @@ impl UpdateRegion for Region { .interiors() .replace( handle, - update(handle, core).map(|object| object.insert(core)), + update(handle, core).map(|object| { + object.insert(core).derive_from(handle, core) + }), ) .expect("Cycle not found"); Region::new(self.exterior().clone(), interiors, self.color()) diff --git a/crates/fj-core/src/operations/update/shell.rs b/crates/fj-core/src/operations/update/shell.rs index 5116b89dd5..6b46c76cd2 100644 --- a/crates/fj-core/src/operations/update/shell.rs +++ b/crates/fj-core/src/operations/update/shell.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Face, Shell}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -66,7 +66,9 @@ impl UpdateShell for Shell { .faces() .replace( handle, - update(handle, core).map(|object| object.insert(core)), + update(handle, core).map(|object| { + object.insert(core).derive_from(handle, core) + }), ) .expect("Face not found"); Shell::new(faces) diff --git a/crates/fj-core/src/operations/update/sketch.rs b/crates/fj-core/src/operations/update/sketch.rs index e13087e44c..192e7da19c 100644 --- a/crates/fj-core/src/operations/update/sketch.rs +++ b/crates/fj-core/src/operations/update/sketch.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Region, Sketch}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -62,7 +62,9 @@ impl UpdateSketch for Sketch { .regions() .replace( handle, - update(handle, core).map(|object| object.insert(core)), + update(handle, core).map(|object| { + object.insert(core).derive_from(handle, core) + }), ) .expect("Region not found"); Sketch::new(regions) diff --git a/crates/fj-core/src/operations/update/solid.rs b/crates/fj-core/src/operations/update/solid.rs index c6ce788bcf..f7882a6372 100644 --- a/crates/fj-core/src/operations/update/solid.rs +++ b/crates/fj-core/src/operations/update/solid.rs @@ -1,6 +1,6 @@ use crate::{ objects::{Shell, Solid}, - operations::insert::Insert, + operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, Core, }; @@ -62,7 +62,9 @@ impl UpdateSolid for Solid { .shells() .replace( handle, - update(handle, core).map(|object| object.insert(core)), + update(handle, core).map(|object| { + object.insert(core).derive_from(handle, core) + }), ) .expect("Shell not found"); Solid::new(shells) diff --git a/crates/fj-core/src/validate/face.rs b/crates/fj-core/src/validate/face.rs index fcf16ee14d..8ba4a8b31d 100644 --- a/crates/fj-core/src/validate/face.rs +++ b/crates/fj-core/src/validate/face.rs @@ -89,6 +89,7 @@ mod tests { objects::{Cycle, Face, HalfEdge, Region}, operations::{ build::{BuildCycle, BuildFace, BuildHalfEdge}, + derive::DeriveFrom, insert::Insert, reverse::Reverse, update::{UpdateCycle, UpdateFace, UpdateRegion}, @@ -161,7 +162,12 @@ mod tests { .interiors() .iter() .cloned() - .map(|cycle| cycle.reverse(&mut core).insert(&mut core)) + .map(|cycle| { + cycle + .reverse(&mut core) + .insert(&mut core) + .derive_from(&cycle, &mut core) + }) .collect::>(); let region = Region::new(