graph: Move `retag` to an enum-dispatched trait

This commit is contained in:
Mikolaj Wielgus 2023-10-18 22:05:22 +00:00
parent b7ff507302
commit ae9dd23b7c
6 changed files with 83 additions and 66 deletions

View File

@ -1,7 +1,7 @@
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, TaggedWeight}, graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, Weight},
primitive::Primitive, primitive::Primitive,
}; };
@ -14,7 +14,7 @@ pub struct Band {
impl Band { impl Band {
pub fn from_dot_prev( pub fn from_dot_prev(
dot: DotIndex, dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>, graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> { ) -> Option<Self> {
let mut next_index = dot.tag(); let mut next_index = dot.tag();
let mut interior = vec![]; let mut interior = vec![];
@ -38,7 +38,7 @@ impl Band {
pub fn from_dot_next( pub fn from_dot_next(
dot: DotIndex, dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>, graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> { ) -> Option<Self> {
let mut prev_index = dot.tag(); let mut prev_index = dot.tag();
let mut interior = vec![]; let mut interior = vec![];

View File

@ -1,8 +1,6 @@
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use crate::graph::{ use crate::graph::{BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, Weight};
BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, TaggedWeight,
};
use crate::primitive::{Bend, Dot, Seg}; use crate::primitive::{Bend, Dot, Seg};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -17,7 +15,7 @@ pub struct Bow {
} }
impl Bow { impl Bow {
pub fn from_bend(index: BendIndex, graph: &StableDiGraph<TaggedWeight, Label, usize>) -> Self { pub fn from_bend(index: BendIndex, graph: &StableDiGraph<Weight, Label, usize>) -> Self {
let bend = index; let bend = index;
let seg1_dot2 = Bend::new(bend, graph).prev().unwrap(); let seg1_dot2 = Bend::new(bend, graph).prev().unwrap();

View File

@ -1,4 +1,5 @@
use enum_as_inner::EnumAsInner; use enum_as_inner::EnumAsInner;
use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -12,8 +13,14 @@ pub trait Ends<Start, Stop> {
fn ends(&self) -> (Start, Stop); fn ends(&self) -> (Start, Stop);
} }
#[enum_dispatch]
pub trait Retag {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex;
}
#[enum_dispatch(Retag)]
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum TaggedWeight { pub enum Weight {
Dot(DotWeight), Dot(DotWeight),
Seg(SegWeight), Seg(SegWeight),
Bend(BendWeight), Bend(BendWeight),
@ -25,10 +32,13 @@ pub struct DotWeight {
pub circle: Circle, pub circle: Circle,
} }
#[derive(Debug, Clone, Copy, PartialEq)] impl Retag for DotWeight {
pub struct BendWeight { fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex {
pub net: i64, TaggedIndex::Dot(DotIndex {
pub cw: bool, index,
marker: PhantomData,
})
}
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -37,6 +47,30 @@ pub struct SegWeight {
pub width: f64, pub width: f64,
} }
impl Retag for SegWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex {
TaggedIndex::Seg(SegIndex {
index,
marker: PhantomData,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BendWeight {
pub net: i64,
pub cw: bool,
}
impl Retag for BendWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex {
TaggedIndex::Bend(BendIndex {
index,
marker: PhantomData,
})
}
}
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum Label { pub enum Label {
End, End,
@ -64,23 +98,6 @@ impl<T> Index<T> {
marker: PhantomData, marker: PhantomData,
} }
} }
pub fn retag(&self, weight: &TaggedWeight) -> TaggedIndex {
match weight {
TaggedWeight::Dot(..) => TaggedIndex::Dot(DotIndex {
index: self.index,
marker: PhantomData,
}),
TaggedWeight::Seg(..) => TaggedIndex::Seg(SegIndex {
index: self.index,
marker: PhantomData,
}),
TaggedWeight::Bend(..) => TaggedIndex::Bend(BendIndex {
index: self.index,
marker: PhantomData,
}),
}
}
} }
pub trait Tag { pub trait Tag {

View File

@ -10,8 +10,8 @@ use spade::Triangulation;
use crate::band::Band; use crate::band::Band;
use crate::bow::Bow; use crate::bow::Bow;
use crate::graph::{ use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, SegIndex, SegWeight, Tag, BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight,
TaggedIndex, TaggedWeight, Tag, TaggedIndex, Weight,
}; };
use crate::primitive::Primitive; use crate::primitive::Primitive;
use crate::segbend::Segbend; use crate::segbend::Segbend;
@ -21,7 +21,7 @@ pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
pub struct Layout { pub struct Layout {
rtree: RTree<RTreeWrapper>, rtree: RTree<RTreeWrapper>,
pub graph: StableDiGraph<TaggedWeight, Label, usize>, pub graph: StableDiGraph<Weight, Label, usize>,
} }
#[debug_invariant(self.graph.node_count() == self.rtree.size())] #[debug_invariant(self.graph.node_count() == self.rtree.size())]
@ -53,13 +53,13 @@ impl Layout {
// Unnecessary retag. It should be possible to elide it. // 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.index).unwrap();
self.remove_from_rtree(index.retag(&weight)); self.remove_from_rtree(weight.retag(index.index));
self.graph.remove_node(index.index); self.graph.remove_node(index.index);
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() + 1))]
pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> { pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> {
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight))); let dot = DotIndex::new(self.graph.add_node(Weight::Dot(weight)));
self.insert_into_rtree(dot.tag()); self.insert_into_rtree(dot.tag());
self.fail_and_remove_if_collides_except(dot, &[])?; self.fail_and_remove_if_collides_except(dot, &[])?;
@ -75,7 +75,7 @@ impl Layout {
to: DotIndex, to: DotIndex,
weight: SegWeight, weight: SegWeight,
) -> Result<SegIndex, ()> { ) -> Result<SegIndex, ()> {
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight))); 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(from.index, seg.index, Label::End);
self.graph.add_edge(seg.index, to.index, Label::End); self.graph.add_edge(seg.index, to.index, Label::End);
@ -126,7 +126,7 @@ impl Layout {
core: DotIndex, core: DotIndex,
weight: BendWeight, weight: BendWeight,
) -> Result<BendIndex, ()> { ) -> Result<BendIndex, ()> {
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight))); 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(from.index, bend.index, Label::End);
self.graph.add_edge(bend.index, to.index, Label::End); self.graph.add_edge(bend.index, to.index, Label::End);
@ -162,7 +162,7 @@ impl Layout {
.first() .first()
.unwrap(); .unwrap();
let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight))); 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(from.index, bend.index, Label::End);
self.graph.add_edge(bend.index, to.index, Label::End); self.graph.add_edge(bend.index, to.index, Label::End);
@ -283,11 +283,11 @@ impl Layout {
let old_weight = dot_weight; let old_weight = dot_weight;
dot_weight.circle.pos = to; dot_weight.circle.pos = to;
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight); *self.graph.node_weight_mut(dot.index).unwrap() = Weight::Dot(dot_weight);
if let Some(..) = self.detect_collision_except(dot, &[]) { if let Some(..) = self.detect_collision_except(dot, &[]) {
// Restore original state. // Restore original state.
*self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(old_weight); *self.graph.node_weight_mut(dot.index).unwrap() = Weight::Dot(old_weight);
self.insert_into_rtree(dot.tag()); self.insert_into_rtree(dot.tag());
self.primitive(dot) self.primitive(dot)

View File

@ -4,27 +4,27 @@ use petgraph::stable_graph::{NodeIndex, StableDiGraph};
use petgraph::Direction::{Incoming, Outgoing}; use petgraph::Direction::{Incoming, Outgoing};
use crate::graph::{ use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, SegWeight, BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, Retag, SegWeight,
TaggedIndex, TaggedWeight, TaggedIndex, Weight,
}; };
use crate::math::{self, Circle}; use crate::math::{self, Circle};
use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait};
#[derive(Debug)] #[derive(Debug)]
pub struct Primitive<'a, Weight> { pub struct Primitive<'a, W> {
pub index: Index<Weight>, pub index: Index<W>,
graph: &'a StableDiGraph<TaggedWeight, Label, usize>, graph: &'a StableDiGraph<Weight, Label, usize>,
} }
impl<'a, Weight> Primitive<'a, Weight> { impl<'a, W> Primitive<'a, W> {
pub fn new(index: Index<Weight>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self { pub fn new(index: Index<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self {
Self { index, graph } Self { index, graph }
} }
pub fn shape(&self) -> Shape { pub fn shape(&self) -> Shape {
match self.tagged_weight() { match self.tagged_weight() {
TaggedWeight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }), Weight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
TaggedWeight::Seg(seg) => { Weight::Seg(seg) => {
let ends = self.ends(); let ends = self.ends();
Shape::Seg(SegShape { Shape::Seg(SegShape {
from: self.primitive(ends.0).weight().circle.pos, from: self.primitive(ends.0).weight().circle.pos,
@ -32,7 +32,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
width: seg.width, width: seg.width,
}) })
} }
TaggedWeight::Bend(bend) => { Weight::Bend(bend) => {
let ends = self.ends(); let ends = self.ends();
let mut bend_shape = BendShape { let mut bend_shape = BendShape {
@ -77,7 +77,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn neighbors(&self) -> impl Iterator<Item = TaggedIndex> + '_ { pub fn neighbors(&self) -> impl Iterator<Item = TaggedIndex> + '_ {
self.graph self.graph
.neighbors_undirected(self.index.index) .neighbors_undirected(self.index.index)
.map(|index| Index::<Label>::new(index).retag(self.graph.node_weight(index).unwrap())) .map(|index| self.graph.node_weight(index).unwrap().retag(index))
} }
pub fn prev_bend(&self) -> Option<BendIndex> { pub fn prev_bend(&self) -> Option<BendIndex> {
@ -99,7 +99,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
{ {
let weight = *self.graph.node_weight(index).unwrap(); let weight = *self.graph.node_weight(index).unwrap();
if let Some(TaggedWeight::Bend(..)) = self.graph.node_weight(index) { if let Some(Weight::Bend(..)) = self.graph.node_weight(index) {
return Some(BendIndex::new(index)); return Some(BendIndex::new(index));
} }
@ -111,7 +111,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn tagged_prev(&self) -> Option<TaggedIndex> { pub fn tagged_prev(&self) -> Option<TaggedIndex> {
self.prev_node() self.prev_node()
.map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap())) .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
} }
fn prev_node(&self) -> Option<NodeIndex<usize>> { fn prev_node(&self) -> Option<NodeIndex<usize>> {
@ -145,7 +145,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
{ {
let weight = *self.graph.node_weight(index).unwrap(); let weight = *self.graph.node_weight(index).unwrap();
if let Some(TaggedWeight::Bend(..)) = self.graph.node_weight(index) { if let Some(Weight::Bend(..)) = self.graph.node_weight(index) {
return Some(BendIndex::new(index)); return Some(BendIndex::new(index));
} }
@ -157,7 +157,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn tagged_next(&self) -> Option<TaggedIndex> { pub fn tagged_next(&self) -> Option<TaggedIndex> {
self.next_node() self.next_node()
.map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap())) .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
} }
fn next_node(&self) -> Option<NodeIndex<usize>> { fn next_node(&self) -> Option<NodeIndex<usize>> {
@ -185,7 +185,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
.next() .next()
} }
pub fn connectable<W>(&self, index: Index<W>) -> bool { pub fn connectable<WW>(&self, index: Index<WW>) -> bool {
let this = self.net(&self.index); let this = self.net(&self.index);
let other = self.net(&index); let other = self.net(&index);
@ -200,24 +200,26 @@ impl<'a, Weight> Primitive<'a, Weight> {
} }
} }
fn net<W>(&self, index: &Index<W>) -> i64 { fn net<WW>(&self, index: &Index<WW>) -> i64 {
match self.graph.node_weight(index.index).unwrap() { match self.graph.node_weight(index.index).unwrap() {
TaggedWeight::Dot(dot) => dot.net, Weight::Dot(dot) => dot.net,
TaggedWeight::Seg(seg) => seg.net, Weight::Seg(seg) => seg.net,
TaggedWeight::Bend(bend) => bend.net, Weight::Bend(bend) => bend.net,
} }
} }
pub fn tagged_index(&self) -> TaggedIndex { pub fn tagged_index(&self) -> TaggedIndex {
self.index self.graph
.retag(self.graph.node_weight(self.index.index).unwrap()) .node_weight(self.index.index)
.unwrap()
.retag(self.index.index)
} }
pub fn tagged_weight(&self) -> TaggedWeight { pub fn tagged_weight(&self) -> Weight {
*self.graph.node_weight(self.index.index).unwrap() *self.graph.node_weight(self.index.index).unwrap()
} }
fn primitive<W>(&self, index: Index<W>) -> Primitive<W> { fn primitive<WW>(&self, index: Index<WW>) -> Primitive<WW> {
Primitive::new(index, &self.graph) Primitive::new(index, &self.graph)
} }
} }

View File

@ -1,7 +1,7 @@
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
graph::{BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, TaggedWeight}, graph::{BendIndex, DotIndex, Ends, Interior, Label, SegIndex, TaggedIndex, Weight},
primitive::{Bend, Dot}, primitive::{Bend, Dot},
}; };
@ -19,7 +19,7 @@ impl Segbend {
pub fn from_dot_prev( pub fn from_dot_prev(
dot: DotIndex, dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>, graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> { ) -> Option<Self> {
let bend = *Dot::new(dot, graph).tagged_prev()?.as_bend()?; let bend = *Dot::new(dot, graph).tagged_prev()?.as_bend()?;
let dot = Bend::new(bend, graph).prev().unwrap(); let dot = Bend::new(bend, graph).prev().unwrap();
@ -33,7 +33,7 @@ impl Segbend {
pub fn from_dot_next( pub fn from_dot_next(
dot: DotIndex, dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>, graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> { ) -> Option<Self> {
let bend = *Dot::new(dot, graph).tagged_next()?.as_bend()?; let bend = *Dot::new(dot, graph).tagged_next()?.as_bend()?;
let dot = Bend::new(bend, graph).next().unwrap(); let dot = Bend::new(bend, graph).next().unwrap();