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;
}
#[enum_dispatch(Retag)]
#[enum_dispatch]
pub trait GetNet {
fn net(&self) -> i64;
}
#[enum_dispatch(Retag, GetNet)]
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum Weight {
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)]
pub struct SegWeight {
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)]
pub struct BendWeight {
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)]
pub enum Label {
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>;
impl MakePrimitive for DotIndex {

View File

@ -10,9 +10,11 @@ use crate::band::Band;
use crate::bow::Bow;
use crate::graph::{
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::shape::{Shape, ShapeTrait};
@ -262,8 +264,7 @@ impl Layout {
}
pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
self.nodes()
.map(|ni| untag!(ni, self.primitive(ni).shape()))
self.nodes().map(|ni| ni.primitive(&self.graph).shape())
}
pub fn node_count(&self) -> usize {
@ -324,16 +325,13 @@ impl Layout {
}
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
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| {
let other_index = wrapper.data;
!untag!(
other_index,
untag!(index, self.primitive(index).connectable(other_index))
)
!index.primitive(&self.graph).connectable(other_index)
})
.filter(|wrapper| !except.contains(&wrapper.data))
.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.edge_count() == old(self.graph.edge_count()))]
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));
}
#[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: 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));
debug_assert!(removed_element.is_some());
}
@ -361,7 +359,7 @@ impl Layout {
fn test_envelopes(&self) -> bool {
!self.rtree.iter().any(|wrapper| {
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);
!self
.rtree

View File

@ -5,12 +5,35 @@ use petgraph::stable_graph::{NodeIndex, StableDiGraph};
use petgraph::Direction::{Incoming, Outgoing};
use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Ends, GenericIndex, GetNodeIndex, Index, Interior,
Label, Retag, SegWeight, Weight,
BendIndex, BendWeight, DotIndex, DotWeight, Ends, GenericIndex, GetNet, GetNodeIndex, Index,
Interior, Label, MakePrimitive, Retag, SegWeight, Weight,
};
use crate::math::{self, Circle};
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]
pub trait TaggedPrevTaggedNext {
fn tagged_prev(&self) -> Option<Index>;
@ -27,7 +50,7 @@ pub trait MakeShape {
fn shape(&self) -> Shape;
}
#[enum_dispatch(MakeShape, TaggedPrevTaggedNext)]
#[enum_dispatch(GetNet, GetGraph, GetConnectable, TaggedPrevTaggedNext, MakeShape)]
pub enum Primitive<'a> {
Dot(Dot<'a>),
Seg(Seg<'a>),
@ -146,7 +169,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
.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 other = self.net(&index);
@ -167,7 +190,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
Weight::Seg(seg) => seg.net,
Weight::Bend(bend) => bend.net,
}
}
}*/
pub fn tagged_index(&self) -> Index {
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> {
fn tagged_prev(&self) -> Option<Index> {
self.prev_node()