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

View File

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

View File

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

View File

@ -10,8 +10,8 @@ use spade::Triangulation;
use crate::band::Band;
use crate::bow::Bow;
use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, SegIndex, SegWeight, Tag,
TaggedIndex, TaggedWeight,
BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight,
Tag, TaggedIndex, Weight,
};
use crate::primitive::Primitive;
use crate::segbend::Segbend;
@ -21,7 +21,7 @@ pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
pub struct Layout {
rtree: RTree<RTreeWrapper>,
pub graph: StableDiGraph<TaggedWeight, Label, usize>,
pub graph: StableDiGraph<Weight, Label, usize>,
}
#[debug_invariant(self.graph.node_count() == self.rtree.size())]
@ -53,13 +53,13 @@ impl Layout {
// Unnecessary retag. It should be possible to elide it.
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);
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() + 1))]
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.fail_and_remove_if_collides_except(dot, &[])?;
@ -75,7 +75,7 @@ impl Layout {
to: DotIndex,
weight: SegWeight,
) -> 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(seg.index, to.index, Label::End);
@ -126,7 +126,7 @@ impl Layout {
core: DotIndex,
weight: BendWeight,
) -> 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(bend.index, to.index, Label::End);
@ -162,7 +162,7 @@ impl Layout {
.first()
.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(bend.index, to.index, Label::End);
@ -283,11 +283,11 @@ impl Layout {
let old_weight = dot_weight;
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, &[]) {
// 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.primitive(dot)

View File

@ -4,27 +4,27 @@ 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, Retag, SegWeight,
TaggedIndex, Weight,
};
use crate::math::{self, Circle};
use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait};
#[derive(Debug)]
pub struct Primitive<'a, Weight> {
pub index: Index<Weight>,
graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
pub struct Primitive<'a, W> {
pub index: Index<W>,
graph: &'a StableDiGraph<Weight, Label, usize>,
}
impl<'a, Weight> Primitive<'a, Weight> {
pub fn new(index: Index<Weight>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self {
impl<'a, W> Primitive<'a, W> {
pub fn new(index: Index<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self {
Self { index, graph }
}
pub fn shape(&self) -> Shape {
match self.tagged_weight() {
TaggedWeight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
TaggedWeight::Seg(seg) => {
Weight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }),
Weight::Seg(seg) => {
let ends = self.ends();
Shape::Seg(SegShape {
from: self.primitive(ends.0).weight().circle.pos,
@ -32,7 +32,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
width: seg.width,
})
}
TaggedWeight::Bend(bend) => {
Weight::Bend(bend) => {
let ends = self.ends();
let mut bend_shape = BendShape {
@ -77,7 +77,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn neighbors(&self) -> impl Iterator<Item = TaggedIndex> + '_ {
self.graph
.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> {
@ -99,7 +99,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
{
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));
}
@ -111,7 +111,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn tagged_prev(&self) -> Option<TaggedIndex> {
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>> {
@ -145,7 +145,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
{
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));
}
@ -157,7 +157,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn tagged_next(&self) -> Option<TaggedIndex> {
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>> {
@ -185,7 +185,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
.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 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() {
TaggedWeight::Dot(dot) => dot.net,
TaggedWeight::Seg(seg) => seg.net,
TaggedWeight::Bend(bend) => bend.net,
Weight::Dot(dot) => dot.net,
Weight::Seg(seg) => seg.net,
Weight::Bend(bend) => bend.net,
}
}
pub fn tagged_index(&self) -> TaggedIndex {
self.index
.retag(self.graph.node_weight(self.index.index).unwrap())
self.graph
.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()
}
fn primitive<W>(&self, index: Index<W>) -> Primitive<W> {
fn primitive<WW>(&self, index: Index<WW>) -> Primitive<WW> {
Primitive::new(index, &self.graph)
}
}

View File

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