From 1a271cd89c7550f3cfcb6596d425394786b3caf7 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Fri, 15 Sep 2023 01:30:23 +0200 Subject: [PATCH] Add `node_count == size` invariant for `Layout` --- src/draw.rs | 2 +- src/layout.rs | 86 +++++++++++++++++++++++++----------------------- src/primitive.rs | 7 ++-- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/draw.rs b/src/draw.rs index a40c29a..cfcf8a1 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -221,7 +221,7 @@ impl<'a> Draw<'a> { } fn seg(&mut self, head: Head, to: Point, width: f64) -> Result<(Head, SegIndex), ()> { - assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.0); + debug_assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.0); let net = self.layout.primitive(head.dot).weight().net; let to_index = self.layout.add_dot(DotWeight { diff --git a/src/layout.rs b/src/layout.rs index de313aa..dbb49eb 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,3 +1,4 @@ +use contracts::debug_invariant; use geo::Point; use petgraph::stable_graph::StableDiGraph; use petgraph::visit::EdgeRef; @@ -22,6 +23,7 @@ pub struct Layout { pub graph: StableDiGraph, } +#[debug_invariant(self.graph.node_count() == self.rtree.size())] impl Layout { pub fn new() -> Self { Layout { @@ -54,8 +56,8 @@ impl Layout { pub fn add_dot(&mut self, weight: DotWeight) -> Result { let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight))); - self.fail_and_remove_if_collides_except(dot, &[])?; self.insert_into_rtree(dot.tag()); + self.fail_and_remove_if_collides_except(dot, &[])?; Ok(dot) } @@ -71,8 +73,8 @@ impl Layout { self.graph.add_edge(from.index, seg.index, Label::End); self.graph.add_edge(seg.index, to.index, Label::End); - self.fail_and_remove_if_collides_except(seg, &[from.tag(), to.tag()])?; self.insert_into_rtree(seg.tag()); + self.fail_and_remove_if_collides_except(seg, &[from.tag(), to.tag()])?; self.graph .node_weight_mut(from.index) @@ -117,8 +119,8 @@ impl Layout { self.graph.add_edge(bend.index, to.index, Label::End); self.graph.add_edge(bend.index, core.index, Label::Core); - self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?; self.insert_into_rtree(bend.tag()); + self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?; Ok(bend) } @@ -166,6 +168,45 @@ impl Layout { result } + pub fn bow(&self, bend: BendIndex) -> Bow { + Bow::from_bend(bend, &self.graph) + } + + pub fn prev_segbend(&self, dot: DotIndex) -> Option { + Segbend::from_dot_prev(dot, &self.graph) + } + + pub fn next_segbend(&self, dot: DotIndex) -> Option { + Segbend::from_dot_next(dot, &self.graph) + } + + fn fail_and_remove_if_collides_except( + &mut self, + index: Index, + except: &[TaggedIndex], + ) -> Result<(), ()> { + if let Some(..) = self.detect_collision_except(index, except) { + self.remove(index); + return Err(()); + } + Ok(()) + } + + pub fn dots(&self) -> impl Iterator + '_ { + self.nodes().filter_map(|ni| ni.as_dot().map(|di| *di)) + } + + pub fn shapes(&self) -> impl Iterator + '_ { + self.nodes() + .map(|ni| untag!(ni, self.primitive(ni).shape())) + } + + fn nodes(&self) -> impl Iterator + '_ { + self.rtree.iter().map(|wrapper| wrapper.data) + } +} + +impl Layout { pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> { let mut cur_bend = self.primitive(dot).outer(); loop { @@ -212,30 +253,6 @@ impl Layout { Primitive::new(index, &self.graph) } - pub fn bow(&self, bend: BendIndex) -> Bow { - Bow::from_bend(bend, &self.graph) - } - - pub fn prev_segbend(&self, dot: DotIndex) -> Option { - Segbend::from_dot_prev(dot, &self.graph) - } - - pub fn next_segbend(&self, dot: DotIndex) -> Option { - Segbend::from_dot_next(dot, &self.graph) - } - - fn fail_and_remove_if_collides_except( - &mut self, - index: Index, - except: &[TaggedIndex], - ) -> Result<(), ()> { - if let Some(..) = self.detect_collision_except(index, except) { - self.graph.remove_node(index.index); - return Err(()); - } - Ok(()) - } - fn detect_collision_except( &self, index: Index, @@ -263,22 +280,9 @@ impl Layout { fn remove_from_rtree(&mut self, index: TaggedIndex) { let shape = untag!(index, self.primitive(index).shape()); - assert!(self + debug_assert!(self .rtree .remove(&RTreeWrapper::new(shape, index)) .is_some()); } - - pub fn dots(&self) -> impl Iterator + '_ { - self.nodes().filter_map(|ni| ni.as_dot().map(|di| *di)) - } - - pub fn shapes(&self) -> impl Iterator + '_ { - self.nodes() - .map(|ni| untag!(ni, self.primitive(ni).shape())) - } - - fn nodes(&self) -> impl Iterator + '_ { - self.rtree.iter().map(|wrapper| wrapper.data) - } } diff --git a/src/primitive.rs b/src/primitive.rs index 215034c..1fce0eb 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -4,7 +4,8 @@ use petgraph::stable_graph::{NodeIndex, StableDiGraph}; use petgraph::Direction::{Incoming, Outgoing}; use crate::graph::{ - BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, SegWeight, TaggedIndex, TaggedWeight, + BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, SegWeight, + TaggedIndex, TaggedWeight, }; use crate::math::{self, Circle}; use crate::shape::{BendShape, DotShape, SegShape, Shape}; @@ -184,7 +185,9 @@ impl<'a, Weight> Primitive<'a, Weight> { let this = self.net(&self.index); let other = self.net(&index); - if this == -1 || other == -1 { + if this == other { + true + } else if this == -1 || other == -1 { true } else if this == -2 || other == -2 { false