diff --git a/src/layout/dot.rs b/src/layout/dot.rs index ff2a6d0..27ef41b 100644 --- a/src/layout/dot.rs +++ b/src/layout/dot.rs @@ -1,6 +1,8 @@ use enum_dispatch::enum_dispatch; use geo::Point; +use petgraph::stable_graph::NodeIndex; + use crate::{ graph::{GenericIndex, GetNodeIndex}, layout::{ @@ -16,7 +18,7 @@ use crate::{ math::Circle, }; -use petgraph::stable_graph::NodeIndex; +use super::geometry::SetPos; #[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] @@ -46,7 +48,7 @@ impl TryFrom for DotIndex { } } -#[enum_dispatch(GetPos, GetWidth)] +#[enum_dispatch(GetPos, SetPos, GetWidth)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum DotWeight { Fixed(FixedDotWeight), @@ -91,6 +93,12 @@ impl GetPos for FixedDotWeight { } } +impl SetPos for FixedDotWeight { + fn set_pos(&mut self, pos: Point) { + self.circle.pos = pos + } +} + impl GetWidth for FixedDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 @@ -112,6 +120,12 @@ impl GetPos for LooseDotWeight { } } +impl SetPos for LooseDotWeight { + fn set_pos(&mut self, pos: Point) { + self.circle.pos = pos + } +} + impl GetWidth for LooseDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 diff --git a/src/layout/geometry/geometry.rs b/src/layout/geometry/geometry.rs index 301c707..32cd8de 100644 --- a/src/layout/geometry/geometry.rs +++ b/src/layout/geometry/geometry.rs @@ -24,6 +24,11 @@ pub trait GetPos { fn pos(&self) -> Point; } +#[enum_dispatch] +pub trait SetPos { + fn set_pos(&mut self, pos: Point); +} + #[enum_dispatch] pub trait GetWidth { fn width(&self) -> f64; @@ -41,7 +46,7 @@ pub enum GeometryLabel { Core, } -pub trait DotWeightTrait: GetPos + GetWidth + Into + Copy {} +pub trait DotWeightTrait: GetPos + SetPos + GetWidth + Into + Copy {} pub trait SegWeightTrait: GetWidth + Into + Copy {} pub trait BendWeightTrait: GetOffset + GetWidth + Into + Copy {} @@ -56,7 +61,7 @@ pub struct Geometry< SI: GetNodeIndex + Into + Copy, BI: GetNodeIndex + Into + Copy, > { - pub graph: StableDiGraph, + graph: StableDiGraph, weight_marker: PhantomData, dot_weight_marker: PhantomData, seg_weight_marker: PhantomData, @@ -140,6 +145,40 @@ impl< bend } + pub fn remove(&mut self, node: GI) { + self.graph.remove_node(node.node_index()); + } + + pub fn move_dot(&mut self, dot: DI, to: Point) { + let mut weight = self.dot_weight(dot); + weight.set_pos(to); + *self.graph.node_weight_mut(dot.node_index()).unwrap() = weight.into() + } + + pub fn flip_bend(&mut self, bend: BI) { + let (from, to) = self.bend_joints(bend); + let from_edge_weight = self + .graph + .remove_edge( + self.graph + .find_edge(from.node_index(), bend.node_index()) + .unwrap(), + ) + .unwrap(); + let to_edge_weight = self + .graph + .remove_edge( + self.graph + .find_edge(bend.node_index(), to.node_index()) + .unwrap(), + ) + .unwrap(); + self.graph + .update_edge(from.node_index(), bend.node_index(), to_edge_weight); + self.graph + .update_edge(bend.node_index(), to.node_index(), from_edge_weight); + } + pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option) { if let Some(old_inner_edge) = self .graph diff --git a/src/layout/layout.rs b/src/layout/layout.rs index b0f2727..a39f82c 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -18,7 +18,7 @@ use crate::guide::Guide; use crate::layout::bend::BendIndex; use crate::layout::dot::DotWeight; use crate::layout::geometry::{ - BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, SegWeightTrait, + BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, SegWeightTrait, }; use crate::layout::{ bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, @@ -188,7 +188,7 @@ impl Layout { .unwrap(); self.remove_from_rtree(weight.retag(node.node_index())); - self.geometry.graph.remove_node(node.node_index()); + self.geometry.remove(node); } // TODO: This method shouldn't be public. @@ -729,12 +729,6 @@ impl Layout { .add_bend(from.into(), to.into(), core.into(), weight); self.geometry.reattach_bend(bend.into(), Some(inner)); - self.geometry.graph.update_edge( - inner.node_index(), - bend.node_index(), - GeometryLabel::Outer, - ); - self.insert_into_rtree(bend.into()); self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; Ok(bend) @@ -744,15 +738,7 @@ impl Layout { #[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))] pub fn flip_bend(&mut self, bend: FixedBendIndex) { self.remove_from_rtree(bend.into()); - - let Some(GeometryWeight::FixedBend(weight)) = - self.geometry.graph.node_weight_mut(bend.node_index()) - else { - unreachable!(); - }; - - weight.cw = !weight.cw; - + self.geometry.flip_bend(bend.into()); self.insert_into_rtree(bend.into()); } @@ -821,32 +807,12 @@ impl Layout { ) -> Result<(), Infringement> { self.remove_from_rtree_with_limbs(dot.into()); - let mut weight = *self.geometry.graph.node_weight(dot.node_index()).unwrap(); - let old_weight = weight; - - match weight { - GeometryWeight::FixedDot(ref mut fixed) => { - fixed.circle.pos = to; - } - GeometryWeight::LooseDot(ref mut loose) => { - loose.circle.pos = to; - } - _ => unreachable!(), - } - - *self - .geometry - .graph - .node_weight_mut(dot.node_index()) - .unwrap() = weight; + let old_pos = self.geometry.dot_weight(dot).pos(); + self.geometry.move_dot(dot, to); if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) { // Restore original state. - *self - .geometry - .graph - .node_weight_mut(dot.node_index()) - .unwrap() = old_weight; + self.geometry.move_dot(dot, old_pos); self.insert_into_rtree_with_limbs(dot.into()); return Err(infringement);