From 5a0fec9618aca8d2ea7aa6f66bd861bf0a861c82 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 16 Jul 2025 19:35:51 +0200 Subject: [PATCH] fix(geometry/recording_with_rtree): Some more fixes against bend bbox invalidation 1f8ace9c77e99d2c7b429e20b1bb5c93107b0e34 did not fix all the bbox invalidation problems, hopefully this gets this right now. --- src/geometry/with_rtree.rs | 55 ++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/geometry/with_rtree.rs b/src/geometry/with_rtree.rs index ef41661..b597553 100644 --- a/src/geometry/with_rtree.rs +++ b/src/geometry/with_rtree.rs @@ -196,8 +196,26 @@ impl< } pub fn remove_bend(&mut self, bend: BI) { + // Note how we can't use `.modify_bend(...)` to update the envelopes + // here because it starts iteration from the bend we currently operate + // on, which obviously does not exist after deletion. + + let mut rail = bend; + + while let Some(outer) = self.geometry.outer(rail) { + Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(outer))); + rail = outer; + } + + let mut maybe_rail = self.geometry.outer(bend); + Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(bend))); self.geometry.remove_primitive(bend.into()); + + while let Some(outer) = maybe_rail { + self.rtree.insert(self.make_bend_bbox(outer)); + maybe_rail = Some(outer); + } } pub fn remove_compound(&mut self, compound: GenericIndex) { @@ -230,23 +248,9 @@ impl< } pub fn shift_bend(&mut self, bend: BI, offset: f64) { - let mut rail = bend; - - while let Some(outer) = self.geometry.outer(rail) { - Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(outer))); - rail = outer; - } - - Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(bend))); - self.geometry.shift_bend(bend, offset); - self.rtree.insert(self.make_bend_bbox(bend)); - - rail = bend; - - while let Some(outer) = self.geometry.outer(rail) { - self.rtree.insert(self.make_bend_bbox(outer)); - rail = outer; - } + self.modify_bend(bend, |geometry, bend| { + geometry.shift_bend(bend, offset); + }); } pub fn flip_bend(&mut self, bend: BI) { @@ -255,6 +259,15 @@ impl< } pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option) { + self.modify_bend(bend, |geometry, bend| { + geometry.reattach_bend(bend, maybe_new_inner); + }); + } + + fn modify_bend(&mut self, bend: BI, f: F) + where + F: FnOnce(&mut Geometry, BI), + { let mut rail = bend; while let Some(outer) = self.geometry.outer(rail) { @@ -263,7 +276,9 @@ impl< } Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(bend))); - self.geometry.reattach_bend(bend, maybe_new_inner); + + f(&mut self.geometry, bend); + self.rtree.insert(self.make_bend_bbox(bend)); rail = bend; @@ -506,8 +521,8 @@ impl< } // Because removal of a bend will invalidate bboxes of the bends wrapped - // around it, we first remove the bends from the R-tree, and their nodes - // from the graph only afterwards. + // around it, we first remove all the edited bends from the R-tree, and + // their nodes from the graph only afterwards. for (bend, (maybe_old_data, ..)) in &edit.bends { if maybe_old_data.is_some() { Self::rtree_remove_must_be_successful(