diff --git a/src/layout.rs b/src/layout.rs index 618f598..0c814ad 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -24,8 +24,8 @@ use crate::guide::Guide; use crate::loose::{GetNextLoose, Loose, LooseIndex}; use crate::math::NoTangents; use crate::primitive::{ - GenericPrimitive, GetConnectable, GetCore, GetEnds, GetInnerOuter, GetOtherEnd, GetWeight, - MakeShape, + GenericPrimitive, GetConnectable, GetCore, GetDependents, GetEnds, GetInnerOuter, GetOtherEnd, + GetWeight, MakeShape, }; use crate::segbend::Segbend; use crate::shape::{Shape, ShapeTrait}; @@ -809,11 +809,7 @@ impl Layout { to: Point, infringables: &[GeometryIndex], ) -> Result<(), Infringement> { - self.primitive(dot) - .seg() - .map(|seg| self.remove_from_rtree(seg.into())); - self.remove_from_rtree(self.primitive(dot).bend().into()); - self.remove_from_rtree(dot.into()); + self.remove_from_rtree_with_dependents(dot.into()); let mut dot_weight = self.primitive(dot).weight(); let old_weight = dot_weight; @@ -827,20 +823,11 @@ impl Layout { *self.geometry.node_weight_mut(dot.node_index()).unwrap() = GeometryWeight::LooseDot(old_weight); - self.insert_into_rtree(dot.into()); - self.insert_into_rtree(self.primitive(dot).bend().into()); - self.primitive(dot) - .seg() - .map(|seg| self.insert_into_rtree(seg.into())); + self.insert_into_rtree_with_dependents(dot.into()); return Err(infringement); } - self.insert_into_rtree(dot.into()); - self.insert_into_rtree(self.primitive(dot).bend().into()); - self.primitive(dot) - .seg() - .map(|seg| self.insert_into_rtree(seg.into())); - + self.insert_into_rtree_with_dependents(dot.into()); Ok(()) } @@ -884,6 +871,16 @@ impl Layout { .and_then(|collidee| Some(Collision(shape, collidee))) } + #[debug_ensures(self.geometry.node_count() == old(self.geometry.node_count()))] + #[debug_ensures(self.geometry.edge_count() == old(self.geometry.edge_count()))] + fn insert_into_rtree_with_dependents(&mut self, node: GeometryIndex) { + self.insert_into_rtree(node); + + for dependent in node.primitive(self).dependents() { + self.insert_into_rtree(dependent); + } + } + #[debug_ensures(self.geometry.node_count() == old(self.geometry.node_count()))] #[debug_ensures(self.geometry.edge_count() == old(self.geometry.edge_count()))] fn insert_into_rtree(&mut self, node: GeometryIndex) { @@ -891,6 +888,16 @@ impl Layout { self.rtree.insert(RTreeWrapper::new(shape, node)); } + #[debug_ensures(self.geometry.node_count() == old(self.geometry.node_count()))] + #[debug_ensures(self.geometry.edge_count() == old(self.geometry.edge_count()))] + fn remove_from_rtree_with_dependents(&mut self, node: GeometryIndex) { + for dependent in node.primitive(self).dependents() { + self.remove_from_rtree(dependent); + } + + self.remove_from_rtree(node); + } + #[debug_ensures(self.geometry.node_count() == old(self.geometry.node_count()))] #[debug_ensures(self.geometry.edge_count() == old(self.geometry.edge_count()))] fn remove_from_rtree(&mut self, node: GeometryIndex) { diff --git a/src/primitive.rs b/src/primitive.rs index b48bc58..7f615fd 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -6,10 +6,11 @@ use petgraph::Direction::{Incoming, Outgoing}; use crate::connectivity::{BandIndex, ComponentIndex, GetNet}; use crate::geometry::{ - DotIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, GeometryIndex, - GeometryLabel, GeometryWeight, GetBandIndex, GetComponentIndex, GetOffset, GetWidth, - LoneLooseSegIndex, LoneLooseSegWeight, LooseBendIndex, LooseBendWeight, LooseDotIndex, - LooseDotWeight, MakePrimitive, Retag, SeqLooseSegIndex, SeqLooseSegWeight, + BendIndex, DotIndex, FixedBendIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, + FixedSegIndex, FixedSegWeight, GeometryIndex, GeometryLabel, GeometryWeight, GetBandIndex, + GetComponentIndex, GetOffset, GetWidth, LoneLooseSegIndex, LoneLooseSegWeight, LooseBendIndex, + LooseBendWeight, LooseDotIndex, LooseDotWeight, MakePrimitive, Retag, SegIndex, + SeqLooseSegIndex, SeqLooseSegWeight, }; use crate::graph::{GenericIndex, GetNodeIndex}; use crate::layout::Layout; @@ -42,6 +43,24 @@ pub trait MakeShape { fn shape(&self) -> Shape; } +#[enum_dispatch] +pub trait GetDependents { + fn dependents(&self) -> Vec { + let mut v = vec![]; + v.extend(self.segs().into_iter().map(Into::::into)); + v.extend(self.bends().into_iter().map(Into::::into)); + v + } + + fn segs(&self) -> Vec { + vec![] + } + + fn bends(&self) -> Vec { + vec![] + } +} + pub trait GetInterior { fn interior(&self) -> Vec; } @@ -208,7 +227,7 @@ macro_rules! impl_loose_primitive { }; } -#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape)] +#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape, GetDependents)] pub enum Primitive<'a> { FixedDot(FixedDot<'a>), LooseDot(LooseDot<'a>), @@ -319,6 +338,42 @@ impl<'a> MakeShape for FixedDot<'a> { }) } } + +impl<'a> GetDependents for FixedDot<'a> { + fn segs(&self) -> Vec { + self.adjacents() + .into_iter() + .filter_map( + |node| match self.layout.geometry().node_weight(node).unwrap() { + GeometryWeight::FixedSeg(seg) => { + Some(SegIndex::Fixed(FixedSegIndex::new(node))) + } + GeometryWeight::LoneLooseSeg(seg) => { + Some(SegIndex::LoneLoose(LoneLooseSegIndex::new(node).into())) + } + GeometryWeight::SeqLooseSeg(seg) => { + Some(SegIndex::SeqLoose(SeqLooseSegIndex::new(node).into())) + } + _ => None, + }, + ) + .collect() + } + + fn bends(&self) -> Vec { + self.adjacents() + .into_iter() + .filter(|node| { + matches!( + self.layout.geometry().node_weight(*node).unwrap(), + GeometryWeight::FixedBend(..) + ) + }) + .map(|node| FixedBendIndex::new(node).into()) + .collect() + } +} + impl<'a> GetFirstRail for FixedDot<'a> {} pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>; @@ -361,6 +416,20 @@ impl<'a> MakeShape for LooseDot<'a> { } } +impl<'a> GetDependents for LooseDot<'a> { + fn segs(&self) -> Vec { + if let Some(seg) = self.seg() { + vec![seg.into()] + } else { + vec![] + } + } + + fn bends(&self) -> Vec { + vec![self.bend().into()] + } +} + pub type FixedSeg<'a> = GenericPrimitive<'a, FixedSegWeight>; impl_fixed_primitive!(FixedSeg, FixedSegWeight); @@ -375,6 +444,8 @@ impl<'a> MakeShape for FixedSeg<'a> { } } +impl<'a> GetDependents for FixedSeg<'a> {} + impl<'a> GetEnds for FixedSeg<'a> { fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { let v = self.adjacents(); @@ -398,6 +469,8 @@ impl<'a> MakeShape for LoneLooseSeg<'a> { } } +impl<'a> GetDependents for LoneLooseSeg<'a> {} + impl<'a> GetWidth for LoneLooseSeg<'a> { fn width(&self) -> f64 { self.primitive(self.ends().1).weight().width() @@ -430,6 +503,8 @@ impl<'a> MakeShape for SeqLooseSeg<'a> { } } +impl<'a> GetDependents for SeqLooseSeg<'a> {} + impl<'a> GetWidth for SeqLooseSeg<'a> { fn width(&self) -> f64 { self.primitive(self.ends().1).weight().width() @@ -491,6 +566,8 @@ impl<'a> MakeShape for FixedBend<'a> { } } +impl<'a> GetDependents for FixedBend<'a> {} + impl<'a> GetEnds for FixedBend<'a> { fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { let v = self.adjacents(); @@ -550,6 +627,8 @@ impl<'a> MakeShape for LooseBend<'a> { } } +impl<'a> GetDependents for LooseBend<'a> {} + impl<'a> GetWidth for LooseBend<'a> { fn width(&self) -> f64 { self.primitive(self.ends().1).weight().width()