From 6317d8b08a272ff0293242a8842ba20c0b8950b2 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Mon, 21 Jul 2025 14:02:21 +0200 Subject: [PATCH] feat(geometry/geometry): Create outward bend walker, use it for R-tree updates Drawing and above abstraction layers do not use it yet, but this will change soon. --- src/drawing/primitive.rs | 5 ++-- src/geometry/geometry.rs | 50 +++++++++++++++++++++++++++++++++++--- src/geometry/with_rtree.rs | 34 ++++++++++---------------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/drawing/primitive.rs b/src/drawing/primitive.rs index e8c1105..8a69413 100644 --- a/src/drawing/primitive.rs +++ b/src/drawing/primitive.rs @@ -488,7 +488,8 @@ impl LooseBend<'_, CW, Cel, R> { pub fn outer(&self) -> Option { self.drawing() .geometry() - .outer(self.bend_index()) - .map(|ni| LooseBendIndex::new(ni.petgraph_index())) + .outers(self.bend_index()) + .next() + .map(|node| LooseBendIndex::new(node.petgraph_index())) } } diff --git a/src/geometry/geometry.rs b/src/geometry/geometry.rs index 2753014..e43f105 100644 --- a/src/geometry/geometry.rs +++ b/src/geometry/geometry.rs @@ -7,10 +7,11 @@ use enum_dispatch::enum_dispatch; use geo::Point; use petgraph::{ stable_graph::{NodeIndex, StableDiGraph}, - visit::EdgeRef, + visit::{EdgeRef, Walker}, Direction::{Incoming, Outgoing}, }; use serde::{Deserialize, Serialize}; +use std::collections::VecDeque; use crate::{ drawing::{ @@ -520,6 +521,45 @@ impl, DW, SW, BW, CW, Cel, PI, DI, SI, BI> } } +pub struct OutwardWalker { + frontier: VecDeque, +} + +impl OutwardWalker { + pub fn new(initial_frontier: impl Iterator) -> Self { + let mut frontier = VecDeque::new(); + frontier.extend(initial_frontier); + + Self { frontier } + } +} + +impl< + PW: Copy + Retag, + DW, + SW, + BW, + CW, + Cel, + PI: TryInto + TryInto + TryInto, + DI, + SI, + BI: Copy + GetPetgraphIndex, + > Walker<&Geometry> for OutwardWalker +{ + type Item = BI; + + fn walk_next( + &mut self, + geometry: &Geometry, + ) -> Option { + let front = self.frontier.pop_front()?; + self.frontier.extend(geometry.outers(front)); + + Some(front) + } +} + impl< PW: Copy + Retag, DW, @@ -576,16 +616,20 @@ impl< }) } - pub fn outer(&self, bend: BI) -> Option { + pub fn outers(&self, bend: BI) -> impl Iterator + '_ { self.graph .edges_directed(bend.petgraph_index(), Outgoing) - .find(|edge| matches!(edge.weight(), GeometryLabel::Outer)) + .filter(|edge| matches!(edge.weight(), GeometryLabel::Outer)) .map(|edge| { self.primitive_index(edge.target()) .try_into() .unwrap_or_else(|_| unreachable!()) }) } + + pub fn outwards(&self, bend: BI) -> OutwardWalker { + OutwardWalker::new(self.outers(bend)) + } } impl, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, DI, SI, BI> diff --git a/src/geometry/with_rtree.rs b/src/geometry/with_rtree.rs index 19a93c6..49d2301 100644 --- a/src/geometry/with_rtree.rs +++ b/src/geometry/with_rtree.rs @@ -5,7 +5,7 @@ use contracts_try::debug_invariant; use derive_getters::Getters; use geo::Point; -use petgraph::stable_graph::StableDiGraph; +use petgraph::{stable_graph::StableDiGraph, visit::Walker}; use rstar::{primitives::GeomWithData, Envelope, RTree, RTreeObject, AABB}; use crate::{ @@ -194,21 +194,17 @@ impl< // 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 outwards = self.geometry.outwards(bend); + while let Some(next) = outwards.walk_next(&self.geometry) { + Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(next))); } - 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); + let mut outwards = self.geometry.outwards(bend); + while let Some(next) = outwards.walk_next(&self.geometry) { + self.rtree.insert(self.make_bend_bbox(next)); } } @@ -273,11 +269,9 @@ impl< where F: FnOnce(&mut Geometry, BI), { - 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 outwards = self.geometry.outwards(bend); + while let Some(next) = outwards.walk_next(&self.geometry) { + Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(next))); } Self::rtree_remove_must_be_successful(self.rtree.remove(&self.make_bend_bbox(bend))); @@ -286,11 +280,9 @@ impl< 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; + let mut outwards = self.geometry.outwards(bend); + while let Some(next) = outwards.walk_next(&self.geometry) { + self.rtree.insert(self.make_bend_bbox(next)); } }