graph,primitive: Use enum_dispatch, rely on generics less

This commit is contained in:
Mikolaj Wielgus 2023-10-19 20:07:26 +00:00
parent 4e21ff754d
commit 708fbb98f1
8 changed files with 226 additions and 197 deletions

View File

@ -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<TaggedIndex>,
interior: Vec<Index>,
}
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<TaggedIndex> for Band {
fn interior(&self) -> Vec<TaggedIndex> {
impl Interior<Index> for Band {
fn interior(&self) -> Vec<Index> {
// FIXME: Unnecessary clone. There should be a better way to do it.
self.interior.clone()
}

View File

@ -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<TaggedIndex> for Bow {
fn interior(&self) -> Vec<TaggedIndex> {
impl Interior<Index> for Bow {
fn interior(&self) -> Vec<Index> {
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),
]
}
}

View File

@ -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 {

View File

@ -15,7 +15,7 @@ pub trait Ends<Start, Stop> {
#[enum_dispatch]
pub trait Retag {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex;
fn retag(&self, index: NodeIndex<usize>) -> Index;
}
#[enum_dispatch(Retag)]
@ -33,9 +33,9 @@ pub struct DotWeight {
}
impl Retag for DotWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex {
TaggedIndex::Dot(DotIndex {
index,
fn retag(&self, index: NodeIndex<usize>) -> 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<usize>) -> TaggedIndex {
TaggedIndex::Seg(SegIndex {
index,
fn retag(&self, index: NodeIndex<usize>) -> 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<usize>) -> TaggedIndex {
TaggedIndex::Bend(BendIndex {
index,
fn retag(&self, index: NodeIndex<usize>) -> 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<usize>;
}
#[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<T> {
pub index: NodeIndex<usize>,
marker: PhantomData<T>,
pub struct GenericIndex<W> {
node_index: NodeIndex<usize>,
marker: PhantomData<W>,
}
impl<T> Index<T> {
impl<W> GenericIndex<W> {
pub fn new(index: NodeIndex<usize>) -> Self {
Self {
index,
node_index: index,
marker: PhantomData,
}
}
}
impl<W> GetNodeIndex for GenericIndex<W> {
fn node_index(&self) -> NodeIndex<usize> {
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<DotWeight>;
pub type DotIndex = GenericIndex<DotWeight>;
impl Tag for DotIndex {
fn tag(&self) -> TaggedIndex {
TaggedIndex::Dot(*self)
fn tag(&self) -> Index {
Index::Dot(*self)
}
}
pub type SegIndex = Index<SegWeight>;
pub type SegIndex = GenericIndex<SegWeight>;
impl Tag for SegIndex {
fn tag(&self) -> TaggedIndex {
TaggedIndex::Seg(*self)
fn tag(&self) -> Index {
Index::Seg(*self)
}
}
pub type BendIndex = Index<BendWeight>;
pub type BendIndex = GenericIndex<BendWeight>;
impl Tag for BendIndex {
fn tag(&self) -> TaggedIndex {
TaggedIndex::Bend(*self)
fn tag(&self) -> Index {
Index::Bend(*self)
}
}

View File

@ -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<Shape, TaggedIndex>;
pub type RTreeWrapper = GeomWithData<Shape, Index>;
pub struct Layout {
rtree: RTree<RTreeWrapper>,
@ -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<TaggedIndex>) {
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<Index>) {
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<W: std::marker::Copy>(&mut self, index: Index<W>) {
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<SegIndex, ()> {
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<BendIndex, ()> {
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<BendIndex, ()> {
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<BendIndex, ()> {
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<W: std::marker::Copy>(
fn fail_and_remove_if_collides_except(
&mut self,
index: Index<W>,
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<Item = TaggedIndex> + '_ {
fn nodes(&self) -> impl Iterator<Item = Index> + '_ {
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<W>(&self, index: Index<W>) -> Primitive<W> {
Primitive::new(index, &self.graph)
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W> {
GenericPrimitive::new(index, &self.graph)
}
fn detect_collision_except<W>(
&self,
index: Index<W>,
except: &[TaggedIndex],
) -> Option<TaggedIndex>
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<Index> {
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

View File

@ -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 {

View File

@ -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<W>,
pub struct GenericPrimitive<'a, W> {
pub index: GenericIndex<W>,
graph: &'a StableDiGraph<Weight, Label, usize>,
}
impl<'a, W> Primitive<'a, W> {
pub fn new(index: Index<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self {
impl<'a, W> GenericPrimitive<'a, W> {
pub fn new(index: GenericIndex<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> 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<Item = TaggedIndex> + '_ {
pub fn neighbors(&self) -> impl Iterator<Item = Index> + '_ {
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<BendIndex> {
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<TaggedIndex> {
pub fn tagged_prev(&self) -> Option<Index> {
self.prev_node()
.map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
}
fn prev_node(&self) -> Option<NodeIndex<usize>> {
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<BendIndex> {
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<TaggedIndex> {
pub fn tagged_next(&self) -> Option<Index> {
self.next_node()
.map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
}
fn next_node(&self) -> Option<NodeIndex<usize>> {
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<DotIndex> {
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<WW>(&self, index: Index<WW>) -> bool {
pub fn connectable<WW>(&self, index: GenericIndex<WW>) -> bool {
let this = self.net(&self.index);
let other = self.net(&index);
@ -173,46 +160,46 @@ impl<'a, W> Primitive<'a, W> {
}
}
fn net<WW>(&self, index: &Index<WW>) -> i64 {
match self.graph.node_weight(index.index).unwrap() {
fn net<WW>(&self, index: &GenericIndex<WW>) -> 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<WW>(&self, index: Index<WW>) -> Primitive<WW> {
Primitive::new(index, &self.graph)
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> {
GenericPrimitive::new(index, &self.graph)
}
}
impl<'a, W> Interior<TaggedIndex> for Primitive<'a, W> {
fn interior(&self) -> Vec<TaggedIndex> {
impl<'a, W> Interior<Index> for GenericPrimitive<'a, W> {
fn interior(&self) -> Vec<Index> {
vec![self.tagged_index()]
}
}
impl<'a, W> Ends<DotIndex, DotIndex> for Primitive<'a, W> {
impl<'a, W> Ends<DotIndex, DotIndex> 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<DotIndex, DotIndex> 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<BendIndex> {
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<BendIndex> {
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<DotIndex> {
@ -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<BendIndex> {
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<BendIndex> {
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();

View File

@ -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<TaggedIndex> for Segbend {
fn interior(&self) -> Vec<TaggedIndex> {
impl Interior<Index> for Segbend {
fn interior(&self) -> Vec<Index> {
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),
]
}
}