graph: Remove the `untag` macro

To accomplish this, some more methods are moved to traits.
This commit is contained in:
Mikolaj Wielgus 2023-10-21 04:32:55 +00:00
parent 4549de098c
commit 403e3e4f98
3 changed files with 82 additions and 28 deletions

View File

@ -21,7 +21,12 @@ pub trait Retag {
fn retag(&self, index: NodeIndex<usize>) -> Index; fn retag(&self, index: NodeIndex<usize>) -> Index;
} }
#[enum_dispatch(Retag)] #[enum_dispatch]
pub trait GetNet {
fn net(&self) -> i64;
}
#[enum_dispatch(Retag, GetNet)]
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum Weight { pub enum Weight {
Dot(DotWeight), Dot(DotWeight),
@ -44,6 +49,12 @@ impl Retag for DotWeight {
} }
} }
impl GetNet for DotWeight {
fn net(&self) -> i64 {
self.net
}
}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct SegWeight { pub struct SegWeight {
pub net: i64, pub net: i64,
@ -59,6 +70,12 @@ impl Retag for SegWeight {
} }
} }
impl GetNet for SegWeight {
fn net(&self) -> i64 {
self.net
}
}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct BendWeight { pub struct BendWeight {
pub net: i64, pub net: i64,
@ -74,6 +91,12 @@ impl Retag for BendWeight {
} }
} }
impl GetNet for BendWeight {
fn net(&self) -> i64 {
self.net
}
}
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum Label { pub enum Label {
End, End,
@ -120,16 +143,6 @@ impl<W> GetNodeIndex for GenericIndex<W> {
} }
} }
macro_rules! untag {
($index:ident, $expr:expr) => {
match $index {
Index::Dot($index) => $expr,
Index::Seg($index) => $expr,
Index::Bend($index) => $expr,
}
};
}
pub type DotIndex = GenericIndex<DotWeight>; pub type DotIndex = GenericIndex<DotWeight>;
impl MakePrimitive for DotIndex { impl MakePrimitive for DotIndex {

View File

@ -10,9 +10,11 @@ use crate::band::Band;
use crate::bow::Bow; use crate::bow::Bow;
use crate::graph::{ use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, GenericIndex, GetNodeIndex, Index, Interior, Label, BendIndex, BendWeight, DotIndex, DotWeight, GenericIndex, GetNodeIndex, Index, Interior, Label,
Retag, SegIndex, SegWeight, Weight, MakePrimitive, Retag, SegIndex, SegWeight, Weight,
};
use crate::primitive::{
GenericPrimitive, GetConnectable, GetWeight, MakeShape, TaggedPrevTaggedNext,
}; };
use crate::primitive::{GenericPrimitive, GetWeight, MakeShape, TaggedPrevTaggedNext};
use crate::segbend::Segbend; use crate::segbend::Segbend;
use crate::shape::{Shape, ShapeTrait}; use crate::shape::{Shape, ShapeTrait};
@ -262,8 +264,7 @@ impl Layout {
} }
pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ { pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
self.nodes() self.nodes().map(|ni| ni.primitive(&self.graph).shape())
.map(|ni| untag!(ni, self.primitive(ni).shape()))
} }
pub fn node_count(&self) -> usize { pub fn node_count(&self) -> usize {
@ -324,16 +325,13 @@ impl Layout {
} }
fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> { fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> {
let shape = untag!(index, self.primitive(index).shape()); let shape = index.primitive(&self.graph).shape();
self.rtree self.rtree
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| { .filter(|wrapper| {
let other_index = wrapper.data; let other_index = wrapper.data;
!untag!( !index.primitive(&self.graph).connectable(other_index)
other_index,
untag!(index, self.primitive(index).connectable(other_index))
)
}) })
.filter(|wrapper| !except.contains(&wrapper.data)) .filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom())) .filter(|wrapper| shape.intersects(wrapper.geom()))
@ -344,14 +342,14 @@ impl Layout {
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn insert_into_rtree(&mut self, index: Index) { fn insert_into_rtree(&mut self, index: Index) {
let shape = untag!(index, self.primitive(index).shape()); let shape = index.primitive(&self.graph).shape();
self.rtree.insert(RTreeWrapper::new(shape, index)); self.rtree.insert(RTreeWrapper::new(shape, index));
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn remove_from_rtree(&mut self, index: Index) { fn remove_from_rtree(&mut self, index: Index) {
let shape = untag!(index, self.primitive(index).shape()); let shape = index.primitive(&self.graph).shape();
let removed_element = self.rtree.remove(&RTreeWrapper::new(shape, index)); let removed_element = self.rtree.remove(&RTreeWrapper::new(shape, index));
debug_assert!(removed_element.is_some()); debug_assert!(removed_element.is_some());
} }
@ -361,7 +359,7 @@ impl Layout {
fn test_envelopes(&self) -> bool { fn test_envelopes(&self) -> bool {
!self.rtree.iter().any(|wrapper| { !self.rtree.iter().any(|wrapper| {
let index = wrapper.data; let index = wrapper.data;
let shape = untag!(index, GenericPrimitive::new(index, &self.graph).shape()); let shape = index.primitive(&self.graph).shape();
let wrapper = RTreeWrapper::new(shape, index); let wrapper = RTreeWrapper::new(shape, index);
!self !self
.rtree .rtree

View File

@ -5,12 +5,35 @@ 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, GenericIndex, GetNodeIndex, Index, Interior, BendIndex, BendWeight, DotIndex, DotWeight, Ends, GenericIndex, GetNet, GetNodeIndex, Index,
Label, Retag, SegWeight, Weight, Interior, Label, MakePrimitive, Retag, SegWeight, 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};
#[enum_dispatch]
pub trait GetGraph {
fn graph(&self) -> &StableDiGraph<Weight, Label, usize>;
}
#[enum_dispatch]
pub trait GetConnectable: GetNet + GetGraph {
fn connectable(&self, index: Index) -> bool {
let this = self.net();
let other = index.primitive(self.graph()).net();
if this == other {
true
} else if this == -1 || other == -1 {
true
} else if this == -2 || other == -2 {
false
} else {
this == other
}
}
}
#[enum_dispatch] #[enum_dispatch]
pub trait TaggedPrevTaggedNext { pub trait TaggedPrevTaggedNext {
fn tagged_prev(&self) -> Option<Index>; fn tagged_prev(&self) -> Option<Index>;
@ -27,7 +50,7 @@ pub trait MakeShape {
fn shape(&self) -> Shape; fn shape(&self) -> Shape;
} }
#[enum_dispatch(MakeShape, TaggedPrevTaggedNext)] #[enum_dispatch(GetNet, GetGraph, GetConnectable, TaggedPrevTaggedNext, MakeShape)]
pub enum Primitive<'a> { pub enum Primitive<'a> {
Dot(Dot<'a>), Dot(Dot<'a>),
Seg(Seg<'a>), Seg(Seg<'a>),
@ -146,7 +169,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
.next() .next()
} }
pub fn connectable<WW>(&self, index: GenericIndex<WW>) -> bool { /*pub fn connectable<WW>(&self, index: GenericIndex<WW>) -> bool {
let this = self.net(&self.index); let this = self.net(&self.index);
let other = self.net(&index); let other = self.net(&index);
@ -167,7 +190,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
Weight::Seg(seg) => seg.net, Weight::Seg(seg) => seg.net,
Weight::Bend(bend) => bend.net, Weight::Bend(bend) => bend.net,
} }
} }*/
pub fn tagged_index(&self) -> Index { pub fn tagged_index(&self) -> Index {
self.graph self.graph
@ -214,6 +237,26 @@ impl<'a, W> Ends<DotIndex, DotIndex> for GenericPrimitive<'a, W> {
} }
} }
impl<'a, W> GetGraph for GenericPrimitive<'a, W> {
fn graph(&self) -> &StableDiGraph<Weight, Label, usize> {
self.graph
}
}
impl<'a, W: GetNet> GetConnectable for GenericPrimitive<'a, W> where
GenericPrimitive<'a, W>: GetWeight<W>
{
}
impl<'a, W: GetNet> GetNet for GenericPrimitive<'a, W>
where
GenericPrimitive<'a, W>: GetWeight<W>,
{
fn net(&self) -> i64 {
self.weight().net()
}
}
impl<'a, W> TaggedPrevTaggedNext for GenericPrimitive<'a, W> { impl<'a, W> TaggedPrevTaggedNext for GenericPrimitive<'a, W> {
fn tagged_prev(&self) -> Option<Index> { fn tagged_prev(&self) -> Option<Index> {
self.prev_node() self.prev_node()