From 708fbb98f10f245b0f30261310ef6693dbfe518d Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Thu, 19 Oct 2023 20:07:26 +0000 Subject: [PATCH] graph,primitive: Use enum_dispatch, rely on generics less --- src/band.rs | 22 +++++--- src/bow.rs | 16 +++--- src/draw.rs | 20 +++---- src/graph.rs | 70 +++++++++++++---------- src/layout.rs | 132 +++++++++++++++++++++---------------------- src/mesh.rs | 9 ++- src/primitive.rs | 142 +++++++++++++++++++++++++---------------------- src/segbend.rs | 12 ++-- 8 files changed, 226 insertions(+), 197 deletions(-) diff --git a/src/band.rs b/src/band.rs index 388392e..cbbb5d3 100644 --- a/src/band.rs +++ b/src/band.rs @@ -1,14 +1,14 @@ use petgraph::stable_graph::StableDiGraph; use crate::{ - graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, Weight}, - primitive::Primitive, + graph::{DotIndex, Ends, Index, Interior, Label, Tag, Weight}, + primitive::GenericPrimitive, }; pub struct Band { from: DotIndex, to: DotIndex, - interior: Vec, + interior: Vec, } impl Band { @@ -19,8 +19,10 @@ impl Band { let mut next_index = dot.tag(); let mut interior = vec![]; - while let Some(index) = untag!(next_index, Primitive::new(next_index, graph).tagged_next()) - { + while let Some(index) = untag!( + next_index, + GenericPrimitive::new(next_index, graph).tagged_next() + ) { interior.push(index); next_index = index; } @@ -43,8 +45,10 @@ impl Band { let mut prev_index = dot.tag(); let mut interior = vec![]; - while let Some(index) = untag!(prev_index, Primitive::new(prev_index, graph).tagged_next()) - { + while let Some(index) = untag!( + prev_index, + GenericPrimitive::new(prev_index, graph).tagged_next() + ) { interior.push(index); prev_index = index; } @@ -61,8 +65,8 @@ impl Band { } } -impl Interior for Band { - fn interior(&self) -> Vec { +impl Interior for Band { + fn interior(&self) -> Vec { // FIXME: Unnecessary clone. There should be a better way to do it. self.interior.clone() } diff --git a/src/bow.rs b/src/bow.rs index e0ec157..4ad5ee2 100644 --- a/src/bow.rs +++ b/src/bow.rs @@ -1,6 +1,6 @@ use petgraph::stable_graph::StableDiGraph; -use crate::graph::{BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, Weight}; +use crate::graph::{BendIndex, DotIndex, Ends, Index, Interior, Label, SegIndex, Weight}; use crate::primitive::{Bend, Dot, Seg}; #[derive(Debug, Clone, Copy)] @@ -46,14 +46,14 @@ impl Bow { } } -impl Interior for Bow { - fn interior(&self) -> Vec { +impl Interior for Bow { + fn interior(&self) -> Vec { vec![ - TaggedIndex::Seg(self.seg1), - TaggedIndex::Dot(self.seg1_dot2), - TaggedIndex::Bend(self.bend), - TaggedIndex::Dot(self.seg2_dot1), - TaggedIndex::Seg(self.seg2), + Index::Seg(self.seg1), + Index::Dot(self.seg1_dot2), + Index::Bend(self.bend), + Index::Dot(self.seg2_dot1), + Index::Seg(self.seg2), ] } } diff --git a/src/draw.rs b/src/draw.rs index 1000a88..af7cc9d 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -3,7 +3,7 @@ use enum_dispatch::enum_dispatch; use geo::{EuclideanDistance, EuclideanLength, Point}; use crate::{ - graph::{BendIndex, BendWeight, DotIndex, DotWeight, Ends, SegIndex, SegWeight, TaggedIndex}, + graph::{BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, SegIndex, SegWeight}, guide::Guide, layout::Layout, math::Circle, @@ -133,7 +133,7 @@ impl<'a> Draw<'a> { .find_map(|(i, tangent)| { self.segbend_around( head, - TaggedIndex::Dot(around), + Index::Dot(around), tangent.start_point(), tangent.end_point(), dirs[i], @@ -168,7 +168,7 @@ impl<'a> Draw<'a> { .find_map(|(i, tangent)| { self.segbend_around( head, - TaggedIndex::Bend(around), + Index::Bend(around), tangent.start_point(), tangent.end_point(), dirs[i], @@ -184,7 +184,7 @@ impl<'a> Draw<'a> { fn segbend_around( &mut self, head: Head, - around: TaggedIndex, + around: Index, from: Point, to: Point, cw: bool, @@ -234,7 +234,7 @@ impl<'a> Draw<'a> { fn segbend( &mut self, head: Head, - around: TaggedIndex, + around: Index, to: Point, cw: bool, width: f64, @@ -255,7 +255,7 @@ impl<'a> Draw<'a> { .layout .add_bend(head.dot, bend_to, around, BendWeight { net, cw }) .map_err(|err| { - self.layout.remove(bend_to); + self.layout.remove(Index::Dot(bend_to)); self.undo_seg(head, seg); err })?; @@ -273,7 +273,7 @@ impl<'a> Draw<'a> { .prev() .map(|prev_dot| { self.layout.remove_interior(&head.segbend); - self.layout.remove(head.dot()); + self.layout.remove(Index::Dot(head.dot())); self.prev_head(prev_dot) }) @@ -295,7 +295,7 @@ impl<'a> Draw<'a> { .layout .add_seg(head.dot(), to_index, SegWeight { net, width }) .map_err(|err| { - self.layout.remove(to_index); + self.layout.remove(Index::Dot(to_index)); err })?; Ok((BareHead { dot: to_index }, seg)) @@ -303,8 +303,8 @@ impl<'a> Draw<'a> { #[debug_ensures(self.layout.node_count() == old(self.layout.node_count() - 2))] fn undo_seg(&mut self, head: BareHead, seg: SegIndex) { - self.layout.remove(seg); - self.layout.remove(head.dot); + self.layout.remove(Index::Seg(seg)); + self.layout.remove(Index::Dot(head.dot)); } fn prev_head(&self, dot: DotIndex) -> Head { diff --git a/src/graph.rs b/src/graph.rs index 4ca5727..e54a7d3 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -15,7 +15,7 @@ pub trait Ends { #[enum_dispatch] pub trait Retag { - fn retag(&self, index: NodeIndex) -> TaggedIndex; + fn retag(&self, index: NodeIndex) -> Index; } #[enum_dispatch(Retag)] @@ -33,9 +33,9 @@ pub struct DotWeight { } impl Retag for DotWeight { - fn retag(&self, index: NodeIndex) -> TaggedIndex { - TaggedIndex::Dot(DotIndex { - index, + fn retag(&self, index: NodeIndex) -> Index { + Index::Dot(DotIndex { + node_index: index, marker: PhantomData, }) } @@ -48,9 +48,9 @@ pub struct SegWeight { } impl Retag for SegWeight { - fn retag(&self, index: NodeIndex) -> TaggedIndex { - TaggedIndex::Seg(SegIndex { - index, + fn retag(&self, index: NodeIndex) -> Index { + Index::Seg(SegIndex { + node_index: index, marker: PhantomData, }) } @@ -63,9 +63,9 @@ pub struct BendWeight { } impl Retag for BendWeight { - fn retag(&self, index: NodeIndex) -> TaggedIndex { - TaggedIndex::Bend(BendIndex { - index, + fn retag(&self, index: NodeIndex) -> Index { + Index::Bend(BendIndex { + node_index: index, marker: PhantomData, }) } @@ -78,62 +78,74 @@ pub enum Label { Core, } +#[enum_dispatch] +pub trait GetNodeIndex { + fn node_index(&self) -> NodeIndex; +} + +#[enum_dispatch(GetNodeIndex)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] -pub enum TaggedIndex { +pub enum Index { Dot(DotIndex), Seg(SegIndex), Bend(BendIndex), } #[derive(Debug, Clone, Copy, PartialEq)] -pub struct Index { - pub index: NodeIndex, - marker: PhantomData, +pub struct GenericIndex { + node_index: NodeIndex, + marker: PhantomData, } -impl Index { +impl GenericIndex { pub fn new(index: NodeIndex) -> Self { Self { - index, + node_index: index, marker: PhantomData, } } } +impl GetNodeIndex for GenericIndex { + fn node_index(&self) -> NodeIndex { + self.node_index + } +} + pub trait Tag { - fn tag(&self) -> TaggedIndex; + fn tag(&self) -> Index; } macro_rules! untag { ($index:ident, $expr:expr) => { match $index { - TaggedIndex::Dot($index) => $expr, - TaggedIndex::Seg($index) => $expr, - TaggedIndex::Bend($index) => $expr, + Index::Dot($index) => $expr, + Index::Seg($index) => $expr, + Index::Bend($index) => $expr, } }; } -pub type DotIndex = Index; +pub type DotIndex = GenericIndex; impl Tag for DotIndex { - fn tag(&self) -> TaggedIndex { - TaggedIndex::Dot(*self) + fn tag(&self) -> Index { + Index::Dot(*self) } } -pub type SegIndex = Index; +pub type SegIndex = GenericIndex; impl Tag for SegIndex { - fn tag(&self) -> TaggedIndex { - TaggedIndex::Seg(*self) + fn tag(&self) -> Index { + Index::Seg(*self) } } -pub type BendIndex = Index; +pub type BendIndex = GenericIndex; impl Tag for BendIndex { - fn tag(&self) -> TaggedIndex { - TaggedIndex::Bend(*self) + fn tag(&self) -> Index { + Index::Bend(*self) } } diff --git a/src/layout.rs b/src/layout.rs index f3e77fc..35a714a 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -10,14 +10,14 @@ use spade::Triangulation; use crate::band::Band; use crate::bow::Bow; use crate::graph::{ - BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight, - Tag, TaggedIndex, Weight, + BendIndex, BendWeight, DotIndex, DotWeight, GenericIndex, GetNodeIndex, Index, Interior, Label, + Retag, SegIndex, SegWeight, Tag, Weight, }; -use crate::primitive::{MakeShape, Primitive}; +use crate::primitive::{GenericPrimitive, MakeShape}; use crate::segbend::Segbend; use crate::shape::{Shape, ShapeTrait}; -pub type RTreeWrapper = GeomWithData; +pub type RTreeWrapper = GeomWithData; pub struct Layout { rtree: RTree, @@ -35,26 +35,26 @@ impl Layout { } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))] - pub fn remove_interior(&mut self, path: &impl Interior) { - for index in path.interior().iter().filter(|index| !index.is_dot()) { - untag!(index, self.remove(*index)); + pub fn remove_interior(&mut self, path: &impl Interior) { + for index in path.interior().into_iter().filter(|index| !index.is_dot()) { + self.remove(index); } // We must remove the dots only after the segs and bends because we need dots to calculate // the shapes, which we need to remove the segs and bends from the R-tree. - for index in path.interior().iter().filter(|index| index.is_dot()) { - untag!(index, self.remove(*index)); + for index in path.interior().into_iter().filter(|index| index.is_dot()) { + self.remove(index); } } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))] - pub fn remove(&mut self, index: Index) { + pub fn remove(&mut self, index: Index) { // Unnecessary retag. It should be possible to elide it. - let weight = *self.graph.node_weight(index.index).unwrap(); + let weight = *self.graph.node_weight(index.node_index()).unwrap(); - self.remove_from_rtree(weight.retag(index.index)); - self.graph.remove_node(index.index); + self.remove_from_rtree(weight.retag(index.node_index())); + self.graph.remove_node(index.node_index()); } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() + 1))] @@ -62,7 +62,7 @@ impl Layout { let dot = DotIndex::new(self.graph.add_node(Weight::Dot(weight))); self.insert_into_rtree(dot.tag()); - self.fail_and_remove_if_collides_except(dot, &[])?; + self.fail_and_remove_if_collides_except(dot.tag(), &[])?; Ok(dot) } @@ -77,20 +77,22 @@ impl Layout { ) -> Result { let seg = SegIndex::new(self.graph.add_node(Weight::Seg(weight))); - self.graph.add_edge(from.index, seg.index, Label::End); - self.graph.add_edge(seg.index, to.index, Label::End); + self.graph + .add_edge(from.node_index(), seg.node_index(), Label::End); + self.graph + .add_edge(seg.node_index(), to.node_index(), Label::End); self.insert_into_rtree(seg.tag()); - self.fail_and_remove_if_collides_except(seg, &[from.tag(), to.tag()])?; + self.fail_and_remove_if_collides_except(seg.tag(), &[from.tag(), to.tag()])?; self.graph - .node_weight_mut(from.index) + .node_weight_mut(from.node_index()) .unwrap() .as_dot_mut() .unwrap() .net = weight.net; self.graph - .node_weight_mut(to.index) + .node_weight_mut(to.node_index()) .unwrap() .as_dot_mut() .unwrap() @@ -105,13 +107,13 @@ impl Layout { &mut self, from: DotIndex, to: DotIndex, - around: TaggedIndex, + around: Index, weight: BendWeight, ) -> Result { match around { - TaggedIndex::Dot(core) => self.add_core_bend(from, to, core, weight), - TaggedIndex::Bend(around) => self.add_outer_bend(from, to, around, weight), - TaggedIndex::Seg(..) => unreachable!(), + Index::Dot(core) => self.add_core_bend(from, to, core, weight), + Index::Bend(around) => self.add_outer_bend(from, to, around, weight), + Index::Seg(..) => unreachable!(), } } @@ -128,12 +130,15 @@ impl Layout { ) -> Result { let bend = BendIndex::new(self.graph.add_node(Weight::Bend(weight))); - self.graph.add_edge(from.index, bend.index, Label::End); - self.graph.add_edge(bend.index, to.index, Label::End); - self.graph.add_edge(bend.index, core.index, Label::Core); + self.graph + .add_edge(from.node_index(), bend.node_index(), Label::End); + self.graph + .add_edge(bend.node_index(), to.node_index(), Label::End); + self.graph + .add_edge(bend.node_index(), core.node_index(), Label::Core); self.insert_into_rtree(bend.tag()); - self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?; + self.fail_and_remove_if_collides_except(bend.tag(), &[from.tag(), to.tag(), core.tag()])?; Ok(bend) } @@ -150,10 +155,10 @@ impl Layout { ) -> Result { let core = *self .graph - .neighbors(inner.index) + .neighbors(inner.node_index()) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(inner.index, *ni).unwrap()) + .edge_weight(self.graph.find_edge(inner.node_index(), *ni).unwrap()) .unwrap() .is_core() }) @@ -164,13 +169,17 @@ impl Layout { let bend = BendIndex::new(self.graph.add_node(Weight::Bend(weight))); - self.graph.add_edge(from.index, bend.index, Label::End); - self.graph.add_edge(bend.index, to.index, Label::End); - self.graph.add_edge(bend.index, core.index, Label::Core); - self.graph.add_edge(inner.index, bend.index, Label::Outer); + self.graph + .add_edge(from.node_index(), bend.node_index(), Label::End); + self.graph + .add_edge(bend.node_index(), to.node_index(), Label::End); + self.graph + .add_edge(bend.node_index(), core.node_index(), Label::Core); + self.graph + .add_edge(inner.node_index(), bend.node_index(), Label::Outer); self.insert_into_rtree(bend.tag()); - self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?; + self.fail_and_remove_if_collides_except(bend.tag(), &[from.tag(), to.tag(), core.tag()])?; Ok(bend) } @@ -182,14 +191,15 @@ impl Layout { if let Some(old_inner_edge) = self .graph - .edges_directed(bend.index, Incoming) + .edges_directed(bend.node_index(), Incoming) .filter(|edge| *edge.weight() == Label::Outer) .next() { self.graph.remove_edge(old_inner_edge.id()); } - self.graph.add_edge(inner.index, bend.index, Label::Outer); + self.graph + .add_edge(inner.node_index(), bend.node_index(), Label::Outer); self.insert_into_rtree(bend.tag()); } @@ -199,13 +209,13 @@ impl Layout { self.remove_from_rtree(bend.tag()); let cw = self .graph - .node_weight(bend.index) + .node_weight(bend.node_index()) .unwrap() .into_bend() .unwrap() .cw; self.graph - .node_weight_mut(bend.index) + .node_weight_mut(bend.node_index()) .unwrap() .as_bend_mut() .unwrap() @@ -236,14 +246,11 @@ impl Layout { #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))] - fn fail_and_remove_if_collides_except( + fn fail_and_remove_if_collides_except( &mut self, - index: Index, - except: &[TaggedIndex], - ) -> Result<(), ()> - where - for<'a> Primitive<'a, W>: MakeShape, - { + index: Index, + except: &[Index], + ) -> Result<(), ()> { if let Some(..) = self.detect_collision_except(index, except) { self.remove(index); return Err(()); @@ -264,7 +271,7 @@ impl Layout { self.graph.node_count() } - fn nodes(&self) -> impl Iterator + '_ { + fn nodes(&self) -> impl Iterator + '_ { self.rtree.iter().map(|wrapper| wrapper.data) } } @@ -286,11 +293,11 @@ impl Layout { let old_weight = dot_weight; dot_weight.circle.pos = to; - *self.graph.node_weight_mut(dot.index).unwrap() = Weight::Dot(dot_weight); + *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::Dot(dot_weight); - if let Some(..) = self.detect_collision_except(dot, &[]) { + if let Some(..) = self.detect_collision_except(dot.tag(), &[]) { // Restore original state. - *self.graph.node_weight_mut(dot.index).unwrap() = Weight::Dot(old_weight); + *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::Dot(old_weight); self.insert_into_rtree(dot.tag()); self.primitive(dot) @@ -313,26 +320,21 @@ impl Layout { Ok(()) } - pub fn primitive(&self, index: Index) -> Primitive { - Primitive::new(index, &self.graph) + pub fn primitive(&self, index: GenericIndex) -> GenericPrimitive { + GenericPrimitive::new(index, &self.graph) } - fn detect_collision_except( - &self, - index: Index, - except: &[TaggedIndex], - ) -> Option - where - for<'a> Primitive<'a, W>: MakeShape, - { - let primitive = self.primitive(index); - let shape = primitive.shape(); + fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option { + let shape = untag!(index, self.primitive(index).shape()); self.rtree .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .filter(|wrapper| { let other_index = wrapper.data; - !untag!(other_index, primitive.connectable(other_index)) + !untag!( + other_index, + untag!(index, self.primitive(index).connectable(other_index)) + ) }) .filter(|wrapper| !except.contains(&wrapper.data)) .filter(|wrapper| shape.intersects(wrapper.geom())) @@ -342,14 +344,14 @@ impl Layout { #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] - fn insert_into_rtree(&mut self, index: TaggedIndex) { + fn insert_into_rtree(&mut self, index: Index) { let shape = untag!(index, self.primitive(index).shape()); self.rtree.insert(RTreeWrapper::new(shape, index)); } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] - fn remove_from_rtree(&mut self, index: TaggedIndex) { + fn remove_from_rtree(&mut self, index: Index) { let shape = untag!(index, self.primitive(index).shape()); let removed_element = self.rtree.remove(&RTreeWrapper::new(shape, index)); debug_assert!(removed_element.is_some()); @@ -360,7 +362,7 @@ impl Layout { fn test_envelopes(&self) -> bool { !self.rtree.iter().any(|wrapper| { let index = wrapper.data; - let shape = untag!(index, Primitive::new(index, &self.graph).shape()); + let shape = untag!(index, GenericPrimitive::new(index, &self.graph).shape()); let wrapper = RTreeWrapper::new(shape, index); !self .rtree diff --git a/src/mesh.rs b/src/mesh.rs index 6325d94..717542b 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -7,7 +7,10 @@ use spade::{ DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation, }; -use crate::{graph::DotIndex, layout::Layout}; +use crate::{ + graph::{DotIndex, GetNodeIndex}, + layout::Layout, +}; use crate::{primitive::MakeShape, shape::ShapeTrait}; #[derive(Debug, Clone)] @@ -51,7 +54,7 @@ impl Mesh { for dot in layout.dots() { let center = layout.primitive(dot).shape().center(); - self.dot_to_vertex[dot.index.index()] = Some(VertexIndex { + self.dot_to_vertex[dot.node_index().index()] = Some(VertexIndex { handle: self.triangulation.insert(Vertex { dot, x: center.x(), @@ -68,7 +71,7 @@ impl Mesh { } pub fn vertex(&self, dot: DotIndex) -> VertexIndex { - self.dot_to_vertex[dot.index.index()].unwrap() + self.dot_to_vertex[dot.node_index().index()].unwrap() } pub fn position(&self, vertex: VertexIndex) -> Point { diff --git a/src/primitive.rs b/src/primitive.rs index 69383d8..def28f6 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -5,56 +5,43 @@ use petgraph::stable_graph::{NodeIndex, StableDiGraph}; use petgraph::Direction::{Incoming, Outgoing}; use crate::graph::{ - BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, Retag, SegWeight, - TaggedIndex, Weight, + BendIndex, BendWeight, DotIndex, DotWeight, Ends, GenericIndex, GetNodeIndex, Index, Interior, + Label, Retag, SegWeight, Weight, }; use crate::math::{self, Circle}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; +#[enum_dispatch] pub trait MakeShape { fn shape(&self) -> Shape; } +#[enum_dispatch(MakeShape)] +pub enum Primitive<'a> { + Dot(Dot<'a>), + Seg(Seg<'a>), + Bend(Bend<'a>), +} + #[derive(Debug)] -pub struct Primitive<'a, W> { - pub index: Index, +pub struct GenericPrimitive<'a, W> { + pub index: GenericIndex, graph: &'a StableDiGraph, } -impl<'a, W> Primitive<'a, W> { - pub fn new(index: Index, graph: &'a StableDiGraph) -> Self { +impl<'a, W> GenericPrimitive<'a, W> { + pub fn new(index: GenericIndex, graph: &'a StableDiGraph) -> Self { Self { index, graph } } - fn inner_radius(&self) -> f64 { - let mut r = 0.0; - let mut layer = BendIndex::new(self.index.index); - - while let Some(inner) = self.primitive(layer).inner() { - r += self.primitive(inner).shape().width(); - layer = inner; - } - - let core_circle = self - .primitive( - self.primitive(BendIndex::new(self.index.index)) - .core() - .unwrap(), - ) - .weight() - .circle; - - core_circle.r + r + 3.0 - } - - pub fn neighbors(&self) -> impl Iterator + '_ { + pub fn neighbors(&self) -> impl Iterator + '_ { self.graph - .neighbors_undirected(self.index.index) + .neighbors_undirected(self.index.node_index()) .map(|index| self.graph.node_weight(index).unwrap().retag(index)) } pub fn prev_bend(&self) -> Option { - let mut prev_index = self.index.index; + let mut prev_index = self.index.node_index(); while let Some(index) = self .graph @@ -82,17 +69,17 @@ impl<'a, W> Primitive<'a, W> { None } - pub fn tagged_prev(&self) -> Option { + pub fn tagged_prev(&self) -> Option { self.prev_node() .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni)) } fn prev_node(&self) -> Option> { self.graph - .neighbors_directed(self.index.index, Incoming) + .neighbors_directed(self.index.node_index(), Incoming) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()) + .edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap()) .unwrap() .is_end() }) @@ -100,7 +87,7 @@ impl<'a, W> Primitive<'a, W> { } pub fn next_bend(&self) -> Option { - let mut prev_index = self.index.index; + let mut prev_index = self.index.node_index(); while let Some(index) = self .graph @@ -128,17 +115,17 @@ impl<'a, W> Primitive<'a, W> { None } - pub fn tagged_next(&self) -> Option { + pub fn tagged_next(&self) -> Option { self.next_node() .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni)) } fn next_node(&self) -> Option> { self.graph - .neighbors_directed(self.index.index, Outgoing) + .neighbors_directed(self.index.node_index(), Outgoing) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()) + .edge_weight(self.graph.find_edge(self.index.node_index(), *ni).unwrap()) .unwrap() .is_end() }) @@ -147,10 +134,10 @@ impl<'a, W> Primitive<'a, W> { pub fn core(&self) -> Option { self.graph - .neighbors(self.index.index) + .neighbors(self.index.node_index()) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()) + .edge_weight(self.graph.find_edge(self.index.node_index(), *ni).unwrap()) .unwrap() .is_core() }) @@ -158,7 +145,7 @@ impl<'a, W> Primitive<'a, W> { .next() } - pub fn connectable(&self, index: Index) -> bool { + pub fn connectable(&self, index: GenericIndex) -> bool { let this = self.net(&self.index); let other = self.net(&index); @@ -173,46 +160,46 @@ impl<'a, W> Primitive<'a, W> { } } - fn net(&self, index: &Index) -> i64 { - match self.graph.node_weight(index.index).unwrap() { + fn net(&self, index: &GenericIndex) -> i64 { + match self.graph.node_weight(index.node_index()).unwrap() { Weight::Dot(dot) => dot.net, Weight::Seg(seg) => seg.net, Weight::Bend(bend) => bend.net, } } - pub fn tagged_index(&self) -> TaggedIndex { + pub fn tagged_index(&self) -> Index { self.graph - .node_weight(self.index.index) + .node_weight(self.index.node_index()) .unwrap() - .retag(self.index.index) + .retag(self.index.node_index()) } pub fn tagged_weight(&self) -> Weight { - *self.graph.node_weight(self.index.index).unwrap() + *self.graph.node_weight(self.index.node_index()).unwrap() } - fn primitive(&self, index: Index) -> Primitive { - Primitive::new(index, &self.graph) + fn primitive(&self, index: GenericIndex) -> GenericPrimitive { + GenericPrimitive::new(index, &self.graph) } } -impl<'a, W> Interior for Primitive<'a, W> { - fn interior(&self) -> Vec { +impl<'a, W> Interior for GenericPrimitive<'a, W> { + fn interior(&self) -> Vec { vec![self.tagged_index()] } } -impl<'a, W> Ends for Primitive<'a, W> { +impl<'a, W> Ends for GenericPrimitive<'a, W> { fn ends(&self) -> (DotIndex, DotIndex) { let v = self .graph - .neighbors_undirected(self.index.index) + .neighbors_undirected(self.index.node_index()) .filter(|ni| { self.graph .edge_weight( self.graph - .find_edge_undirected(self.index.index, *ni) + .find_edge_undirected(self.index.node_index(), *ni) .unwrap() .0, ) @@ -226,17 +213,17 @@ impl<'a, W> Ends for Primitive<'a, W> { } } -pub type Dot<'a> = Primitive<'a, DotWeight>; +pub type Dot<'a> = GenericPrimitive<'a, DotWeight>; impl<'a> Dot<'a> { pub fn bend(&self) -> Option { self.graph - .neighbors_undirected(self.index.index) + .neighbors_undirected(self.index.node_index()) .filter(|ni| { self.graph .edge_weight( self.graph - .find_edge_undirected(self.index.index, *ni) + .find_edge_undirected(self.index.node_index(), *ni) .unwrap() .0, ) @@ -250,10 +237,10 @@ impl<'a> Dot<'a> { pub fn outer(&self) -> Option { self.graph - .neighbors_directed(self.index.index, Incoming) + .neighbors_directed(self.index.node_index(), Incoming) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()) + .edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap()) .unwrap() .is_core() }) @@ -275,7 +262,7 @@ impl<'a> MakeShape for Dot<'a> { } } -pub type Seg<'a> = Primitive<'a, SegWeight>; +pub type Seg<'a> = GenericPrimitive<'a, SegWeight>; impl<'a> Seg<'a> { pub fn next(&self) -> Option { @@ -302,23 +289,23 @@ impl<'a> MakeShape for Seg<'a> { } } -pub type Bend<'a> = Primitive<'a, BendWeight>; +pub type Bend<'a> = GenericPrimitive<'a, BendWeight>; impl<'a> Bend<'a> { - pub fn around(&self) -> TaggedIndex { + pub fn around(&self) -> Index { if let Some(inner) = self.inner() { - TaggedIndex::Bend(inner) + Index::Bend(inner) } else { - TaggedIndex::Dot(self.core().unwrap()) + Index::Dot(self.core().unwrap()) } } pub fn inner(&self) -> Option { self.graph - .neighbors_directed(self.index.index, Incoming) + .neighbors_directed(self.index.node_index(), Incoming) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()) + .edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap()) .unwrap() .is_outer() }) @@ -328,10 +315,10 @@ impl<'a> Bend<'a> { pub fn outer(&self) -> Option { self.graph - .neighbors_directed(self.index.index, Outgoing) + .neighbors_directed(self.index.node_index(), Outgoing) .filter(|ni| { self.graph - .edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()) + .edge_weight(self.graph.find_edge(self.index.node_index(), *ni).unwrap()) .unwrap() .is_outer() }) @@ -351,6 +338,27 @@ impl<'a> Bend<'a> { self.tagged_weight().into_bend().unwrap() } + fn inner_radius(&self) -> f64 { + let mut r = 0.0; + let mut layer = BendIndex::new(self.index.node_index()); + + while let Some(inner) = self.primitive(layer).inner() { + r += self.primitive(inner).shape().width(); + layer = inner; + } + + let core_circle = self + .primitive( + self.primitive(BendIndex::new(self.index.node_index())) + .core() + .unwrap(), + ) + .weight() + .circle; + + core_circle.r + r + 3.0 + } + pub fn cross_product(&self) -> f64 { let center = self.primitive(self.core().unwrap()).weight().circle.pos; let ends = self.ends(); diff --git a/src/segbend.rs b/src/segbend.rs index ee548c6..eafb3a1 100644 --- a/src/segbend.rs +++ b/src/segbend.rs @@ -1,7 +1,7 @@ use petgraph::stable_graph::StableDiGraph; use crate::{ - graph::{BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, Weight}, + graph::{BendIndex, DotIndex, Ends, Index, Interior, Label, SegIndex, Weight}, primitive::{Bend, Dot}, }; @@ -46,12 +46,12 @@ impl Segbend { } } -impl Interior for Segbend { - fn interior(&self) -> Vec { +impl Interior for Segbend { + fn interior(&self) -> Vec { vec![ - TaggedIndex::Bend(self.bend), - TaggedIndex::Dot(self.dot), - TaggedIndex::Seg(self.seg), + Index::Bend(self.bend), + Index::Dot(self.dot), + Index::Seg(self.seg), ] } }