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 petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, Weight}, graph::{DotIndex, Ends, Index, Interior, Label, Tag, Weight},
primitive::Primitive, primitive::GenericPrimitive,
}; };
pub struct Band { pub struct Band {
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
interior: Vec<TaggedIndex>, interior: Vec<Index>,
} }
impl Band { impl Band {
@ -19,8 +19,10 @@ impl Band {
let mut next_index = dot.tag(); let mut next_index = dot.tag();
let mut interior = vec![]; 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); interior.push(index);
next_index = index; next_index = index;
} }
@ -43,8 +45,10 @@ impl Band {
let mut prev_index = dot.tag(); let mut prev_index = dot.tag();
let mut interior = vec![]; 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); interior.push(index);
prev_index = index; prev_index = index;
} }
@ -61,8 +65,8 @@ impl Band {
} }
} }
impl Interior<TaggedIndex> for Band { impl Interior<Index> for Band {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<Index> {
// FIXME: Unnecessary clone. There should be a better way to do it. // FIXME: Unnecessary clone. There should be a better way to do it.
self.interior.clone() self.interior.clone()
} }

View File

@ -1,6 +1,6 @@
use petgraph::stable_graph::StableDiGraph; 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}; use crate::primitive::{Bend, Dot, Seg};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -46,14 +46,14 @@ impl Bow {
} }
} }
impl Interior<TaggedIndex> for Bow { impl Interior<Index> for Bow {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<Index> {
vec![ vec![
TaggedIndex::Seg(self.seg1), Index::Seg(self.seg1),
TaggedIndex::Dot(self.seg1_dot2), Index::Dot(self.seg1_dot2),
TaggedIndex::Bend(self.bend), Index::Bend(self.bend),
TaggedIndex::Dot(self.seg2_dot1), Index::Dot(self.seg2_dot1),
TaggedIndex::Seg(self.seg2), Index::Seg(self.seg2),
] ]
} }
} }

View File

@ -3,7 +3,7 @@ use enum_dispatch::enum_dispatch;
use geo::{EuclideanDistance, EuclideanLength, Point}; use geo::{EuclideanDistance, EuclideanLength, Point};
use crate::{ use crate::{
graph::{BendIndex, BendWeight, DotIndex, DotWeight, Ends, SegIndex, SegWeight, TaggedIndex}, graph::{BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, SegIndex, SegWeight},
guide::Guide, guide::Guide,
layout::Layout, layout::Layout,
math::Circle, math::Circle,
@ -133,7 +133,7 @@ impl<'a> Draw<'a> {
.find_map(|(i, tangent)| { .find_map(|(i, tangent)| {
self.segbend_around( self.segbend_around(
head, head,
TaggedIndex::Dot(around), Index::Dot(around),
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
@ -168,7 +168,7 @@ impl<'a> Draw<'a> {
.find_map(|(i, tangent)| { .find_map(|(i, tangent)| {
self.segbend_around( self.segbend_around(
head, head,
TaggedIndex::Bend(around), Index::Bend(around),
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
@ -184,7 +184,7 @@ impl<'a> Draw<'a> {
fn segbend_around( fn segbend_around(
&mut self, &mut self,
head: Head, head: Head,
around: TaggedIndex, around: Index,
from: Point, from: Point,
to: Point, to: Point,
cw: bool, cw: bool,
@ -234,7 +234,7 @@ impl<'a> Draw<'a> {
fn segbend( fn segbend(
&mut self, &mut self,
head: Head, head: Head,
around: TaggedIndex, around: Index,
to: Point, to: Point,
cw: bool, cw: bool,
width: f64, width: f64,
@ -255,7 +255,7 @@ impl<'a> Draw<'a> {
.layout .layout
.add_bend(head.dot, bend_to, around, BendWeight { net, cw }) .add_bend(head.dot, bend_to, around, BendWeight { net, cw })
.map_err(|err| { .map_err(|err| {
self.layout.remove(bend_to); self.layout.remove(Index::Dot(bend_to));
self.undo_seg(head, seg); self.undo_seg(head, seg);
err err
})?; })?;
@ -273,7 +273,7 @@ impl<'a> Draw<'a> {
.prev() .prev()
.map(|prev_dot| { .map(|prev_dot| {
self.layout.remove_interior(&head.segbend); self.layout.remove_interior(&head.segbend);
self.layout.remove(head.dot()); self.layout.remove(Index::Dot(head.dot()));
self.prev_head(prev_dot) self.prev_head(prev_dot)
}) })
@ -295,7 +295,7 @@ impl<'a> Draw<'a> {
.layout .layout
.add_seg(head.dot(), to_index, SegWeight { net, width }) .add_seg(head.dot(), to_index, SegWeight { net, width })
.map_err(|err| { .map_err(|err| {
self.layout.remove(to_index); self.layout.remove(Index::Dot(to_index));
err err
})?; })?;
Ok((BareHead { dot: to_index }, seg)) 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))] #[debug_ensures(self.layout.node_count() == old(self.layout.node_count() - 2))]
fn undo_seg(&mut self, head: BareHead, seg: SegIndex) { fn undo_seg(&mut self, head: BareHead, seg: SegIndex) {
self.layout.remove(seg); self.layout.remove(Index::Seg(seg));
self.layout.remove(head.dot); self.layout.remove(Index::Dot(head.dot));
} }
fn prev_head(&self, dot: DotIndex) -> Head { fn prev_head(&self, dot: DotIndex) -> Head {

View File

@ -15,7 +15,7 @@ pub trait Ends<Start, Stop> {
#[enum_dispatch] #[enum_dispatch]
pub trait Retag { pub trait Retag {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex; fn retag(&self, index: NodeIndex<usize>) -> Index;
} }
#[enum_dispatch(Retag)] #[enum_dispatch(Retag)]
@ -33,9 +33,9 @@ pub struct DotWeight {
} }
impl Retag for DotWeight { impl Retag for DotWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex { fn retag(&self, index: NodeIndex<usize>) -> Index {
TaggedIndex::Dot(DotIndex { Index::Dot(DotIndex {
index, node_index: index,
marker: PhantomData, marker: PhantomData,
}) })
} }
@ -48,9 +48,9 @@ pub struct SegWeight {
} }
impl Retag for SegWeight { impl Retag for SegWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex { fn retag(&self, index: NodeIndex<usize>) -> Index {
TaggedIndex::Seg(SegIndex { Index::Seg(SegIndex {
index, node_index: index,
marker: PhantomData, marker: PhantomData,
}) })
} }
@ -63,9 +63,9 @@ pub struct BendWeight {
} }
impl Retag for BendWeight { impl Retag for BendWeight {
fn retag(&self, index: NodeIndex<usize>) -> TaggedIndex { fn retag(&self, index: NodeIndex<usize>) -> Index {
TaggedIndex::Bend(BendIndex { Index::Bend(BendIndex {
index, node_index: index,
marker: PhantomData, marker: PhantomData,
}) })
} }
@ -78,62 +78,74 @@ pub enum Label {
Core, Core,
} }
#[enum_dispatch]
pub trait GetNodeIndex {
fn node_index(&self) -> NodeIndex<usize>;
}
#[enum_dispatch(GetNodeIndex)]
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
pub enum TaggedIndex { pub enum Index {
Dot(DotIndex), Dot(DotIndex),
Seg(SegIndex), Seg(SegIndex),
Bend(BendIndex), Bend(BendIndex),
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Index<T> { pub struct GenericIndex<W> {
pub index: NodeIndex<usize>, node_index: NodeIndex<usize>,
marker: PhantomData<T>, marker: PhantomData<W>,
} }
impl<T> Index<T> { impl<W> GenericIndex<W> {
pub fn new(index: NodeIndex<usize>) -> Self { pub fn new(index: NodeIndex<usize>) -> Self {
Self { Self {
index, node_index: index,
marker: PhantomData, marker: PhantomData,
} }
} }
} }
impl<W> GetNodeIndex for GenericIndex<W> {
fn node_index(&self) -> NodeIndex<usize> {
self.node_index
}
}
pub trait Tag { pub trait Tag {
fn tag(&self) -> TaggedIndex; fn tag(&self) -> Index;
} }
macro_rules! untag { macro_rules! untag {
($index:ident, $expr:expr) => { ($index:ident, $expr:expr) => {
match $index { match $index {
TaggedIndex::Dot($index) => $expr, Index::Dot($index) => $expr,
TaggedIndex::Seg($index) => $expr, Index::Seg($index) => $expr,
TaggedIndex::Bend($index) => $expr, Index::Bend($index) => $expr,
} }
}; };
} }
pub type DotIndex = Index<DotWeight>; pub type DotIndex = GenericIndex<DotWeight>;
impl Tag for DotIndex { impl Tag for DotIndex {
fn tag(&self) -> TaggedIndex { fn tag(&self) -> Index {
TaggedIndex::Dot(*self) Index::Dot(*self)
} }
} }
pub type SegIndex = Index<SegWeight>; pub type SegIndex = GenericIndex<SegWeight>;
impl Tag for SegIndex { impl Tag for SegIndex {
fn tag(&self) -> TaggedIndex { fn tag(&self) -> Index {
TaggedIndex::Seg(*self) Index::Seg(*self)
} }
} }
pub type BendIndex = Index<BendWeight>; pub type BendIndex = GenericIndex<BendWeight>;
impl Tag for BendIndex { impl Tag for BendIndex {
fn tag(&self) -> TaggedIndex { fn tag(&self) -> Index {
TaggedIndex::Bend(*self) Index::Bend(*self)
} }
} }

View File

@ -10,14 +10,14 @@ 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, Retag, SegIndex, SegWeight, BendIndex, BendWeight, DotIndex, DotWeight, GenericIndex, GetNodeIndex, Index, Interior, Label,
Tag, TaggedIndex, Weight, Retag, SegIndex, SegWeight, Tag, Weight,
}; };
use crate::primitive::{MakeShape, Primitive}; use crate::primitive::{GenericPrimitive, MakeShape};
use crate::segbend::Segbend; use crate::segbend::Segbend;
use crate::shape::{Shape, ShapeTrait}; use crate::shape::{Shape, ShapeTrait};
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>; pub type RTreeWrapper = GeomWithData<Shape, Index>;
pub struct Layout { pub struct Layout {
rtree: RTree<RTreeWrapper>, rtree: RTree<RTreeWrapper>,
@ -35,26 +35,26 @@ impl Layout {
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))]
pub fn remove_interior(&mut self, path: &impl Interior<TaggedIndex>) { pub fn remove_interior(&mut self, path: &impl Interior<Index>) {
for index in path.interior().iter().filter(|index| !index.is_dot()) { for index in path.interior().into_iter().filter(|index| !index.is_dot()) {
untag!(index, self.remove(*index)); self.remove(index);
} }
// We must remove the dots only after the segs and bends because we need dots to calculate // 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. // 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()) { for index in path.interior().into_iter().filter(|index| index.is_dot()) {
untag!(index, self.remove(*index)); self.remove(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 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. // 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.remove_from_rtree(weight.retag(index.node_index()));
self.graph.remove_node(index.index); self.graph.remove_node(index.node_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))]
@ -62,7 +62,7 @@ impl Layout {
let dot = DotIndex::new(self.graph.add_node(Weight::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.tag(), &[])?;
Ok(dot) Ok(dot)
} }
@ -77,20 +77,22 @@ impl Layout {
) -> Result<SegIndex, ()> { ) -> Result<SegIndex, ()> {
let seg = SegIndex::new(self.graph.add_node(Weight::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
self.graph.add_edge(seg.index, to.index, Label::End); .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.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 self.graph
.node_weight_mut(from.index) .node_weight_mut(from.node_index())
.unwrap() .unwrap()
.as_dot_mut() .as_dot_mut()
.unwrap() .unwrap()
.net = weight.net; .net = weight.net;
self.graph self.graph
.node_weight_mut(to.index) .node_weight_mut(to.node_index())
.unwrap() .unwrap()
.as_dot_mut() .as_dot_mut()
.unwrap() .unwrap()
@ -105,13 +107,13 @@ impl Layout {
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
around: TaggedIndex, around: Index,
weight: BendWeight, weight: BendWeight,
) -> Result<BendIndex, ()> { ) -> Result<BendIndex, ()> {
match around { match around {
TaggedIndex::Dot(core) => self.add_core_bend(from, to, core, weight), Index::Dot(core) => self.add_core_bend(from, to, core, weight),
TaggedIndex::Bend(around) => self.add_outer_bend(from, to, around, weight), Index::Bend(around) => self.add_outer_bend(from, to, around, weight),
TaggedIndex::Seg(..) => unreachable!(), Index::Seg(..) => unreachable!(),
} }
} }
@ -128,12 +130,15 @@ impl Layout {
) -> Result<BendIndex, ()> { ) -> Result<BendIndex, ()> {
let bend = BendIndex::new(self.graph.add_node(Weight::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
self.graph.add_edge(bend.index, to.index, Label::End); .add_edge(from.node_index(), bend.node_index(), Label::End);
self.graph.add_edge(bend.index, core.index, Label::Core); 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.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) Ok(bend)
} }
@ -150,10 +155,10 @@ impl Layout {
) -> Result<BendIndex, ()> { ) -> Result<BendIndex, ()> {
let core = *self let core = *self
.graph .graph
.neighbors(inner.index) .neighbors(inner.node_index())
.filter(|ni| { .filter(|ni| {
self.graph self.graph
.edge_weight(self.graph.find_edge(inner.index, *ni).unwrap()) .edge_weight(self.graph.find_edge(inner.node_index(), *ni).unwrap())
.unwrap() .unwrap()
.is_core() .is_core()
}) })
@ -164,13 +169,17 @@ impl Layout {
let bend = BendIndex::new(self.graph.add_node(Weight::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
self.graph.add_edge(bend.index, to.index, Label::End); .add_edge(from.node_index(), bend.node_index(), Label::End);
self.graph.add_edge(bend.index, core.index, Label::Core); self.graph
self.graph.add_edge(inner.index, bend.index, Label::Outer); .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.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) Ok(bend)
} }
@ -182,14 +191,15 @@ impl Layout {
if let Some(old_inner_edge) = self if let Some(old_inner_edge) = self
.graph .graph
.edges_directed(bend.index, Incoming) .edges_directed(bend.node_index(), Incoming)
.filter(|edge| *edge.weight() == Label::Outer) .filter(|edge| *edge.weight() == Label::Outer)
.next() .next()
{ {
self.graph.remove_edge(old_inner_edge.id()); 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()); self.insert_into_rtree(bend.tag());
} }
@ -199,13 +209,13 @@ impl Layout {
self.remove_from_rtree(bend.tag()); self.remove_from_rtree(bend.tag());
let cw = self let cw = self
.graph .graph
.node_weight(bend.index) .node_weight(bend.node_index())
.unwrap() .unwrap()
.into_bend() .into_bend()
.unwrap() .unwrap()
.cw; .cw;
self.graph self.graph
.node_weight_mut(bend.index) .node_weight_mut(bend.node_index())
.unwrap() .unwrap()
.as_bend_mut() .as_bend_mut()
.unwrap() .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.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_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))] #[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, &mut self,
index: Index<W>, index: Index,
except: &[TaggedIndex], except: &[Index],
) -> Result<(), ()> ) -> Result<(), ()> {
where
for<'a> Primitive<'a, W>: MakeShape,
{
if let Some(..) = self.detect_collision_except(index, except) { if let Some(..) = self.detect_collision_except(index, except) {
self.remove(index); self.remove(index);
return Err(()); return Err(());
@ -264,7 +271,7 @@ impl Layout {
self.graph.node_count() 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) self.rtree.iter().map(|wrapper| wrapper.data)
} }
} }
@ -286,11 +293,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() = 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. // 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.insert_into_rtree(dot.tag());
self.primitive(dot) self.primitive(dot)
@ -313,26 +320,21 @@ impl Layout {
Ok(()) Ok(())
} }
pub fn primitive<W>(&self, index: Index<W>) -> Primitive<W> { pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W> {
Primitive::new(index, &self.graph) GenericPrimitive::new(index, &self.graph)
} }
fn detect_collision_except<W>( fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> {
&self, let shape = untag!(index, self.primitive(index).shape());
index: Index<W>,
except: &[TaggedIndex],
) -> Option<TaggedIndex>
where
for<'a> Primitive<'a, W>: MakeShape,
{
let primitive = self.primitive(index);
let shape = primitive.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!(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| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom())) .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.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: TaggedIndex) { fn insert_into_rtree(&mut self, index: Index) {
let shape = untag!(index, self.primitive(index).shape()); let shape = untag!(index, self.primitive(index).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: TaggedIndex) { fn remove_from_rtree(&mut self, index: Index) {
let shape = untag!(index, self.primitive(index).shape()); let shape = untag!(index, self.primitive(index).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());
@ -360,7 +362,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, Primitive::new(index, &self.graph).shape()); let shape = untag!(index, GenericPrimitive::new(index, &self.graph).shape());
let wrapper = RTreeWrapper::new(shape, index); let wrapper = RTreeWrapper::new(shape, index);
!self !self
.rtree .rtree

View File

@ -7,7 +7,10 @@ use spade::{
DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation, DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation,
}; };
use crate::{graph::DotIndex, layout::Layout}; use crate::{
graph::{DotIndex, GetNodeIndex},
layout::Layout,
};
use crate::{primitive::MakeShape, shape::ShapeTrait}; use crate::{primitive::MakeShape, shape::ShapeTrait};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -51,7 +54,7 @@ impl Mesh {
for dot in layout.dots() { for dot in layout.dots() {
let center = layout.primitive(dot).shape().center(); 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 { handle: self.triangulation.insert(Vertex {
dot, dot,
x: center.x(), x: center.x(),
@ -68,7 +71,7 @@ impl Mesh {
} }
pub fn vertex(&self, dot: DotIndex) -> VertexIndex { 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 { 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 petgraph::Direction::{Incoming, Outgoing};
use crate::graph::{ use crate::graph::{
BendIndex, BendWeight, DotIndex, DotWeight, Ends, Index, Interior, Label, Retag, SegWeight, BendIndex, BendWeight, DotIndex, DotWeight, Ends, GenericIndex, GetNodeIndex, Index, Interior,
TaggedIndex, Weight, Label, 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 MakeShape { pub trait MakeShape {
fn shape(&self) -> Shape; fn shape(&self) -> Shape;
} }
#[enum_dispatch(MakeShape)]
pub enum Primitive<'a> {
Dot(Dot<'a>),
Seg(Seg<'a>),
Bend(Bend<'a>),
}
#[derive(Debug)] #[derive(Debug)]
pub struct Primitive<'a, W> { pub struct GenericPrimitive<'a, W> {
pub index: Index<W>, pub index: GenericIndex<W>,
graph: &'a StableDiGraph<Weight, Label, usize>, graph: &'a StableDiGraph<Weight, Label, usize>,
} }
impl<'a, W> Primitive<'a, W> { impl<'a, W> GenericPrimitive<'a, W> {
pub fn new(index: Index<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self { pub fn new(index: GenericIndex<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self {
Self { index, graph } Self { index, graph }
} }
fn inner_radius(&self) -> f64 { pub fn neighbors(&self) -> impl Iterator<Item = Index> + '_ {
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> + '_ {
self.graph self.graph
.neighbors_undirected(self.index.index) .neighbors_undirected(self.index.node_index())
.map(|index| self.graph.node_weight(index).unwrap().retag(index)) .map(|index| self.graph.node_weight(index).unwrap().retag(index))
} }
pub fn prev_bend(&self) -> Option<BendIndex> { 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 while let Some(index) = self
.graph .graph
@ -82,17 +69,17 @@ impl<'a, W> Primitive<'a, W> {
None None
} }
pub fn tagged_prev(&self) -> Option<TaggedIndex> { pub fn tagged_prev(&self) -> Option<Index> {
self.prev_node() self.prev_node()
.map(|ni| self.graph.node_weight(ni).unwrap().retag(ni)) .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
} }
fn prev_node(&self) -> Option<NodeIndex<usize>> { fn prev_node(&self) -> Option<NodeIndex<usize>> {
self.graph self.graph
.neighbors_directed(self.index.index, Incoming) .neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_end() .is_end()
}) })
@ -100,7 +87,7 @@ impl<'a, W> Primitive<'a, W> {
} }
pub fn next_bend(&self) -> Option<BendIndex> { 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 while let Some(index) = self
.graph .graph
@ -128,17 +115,17 @@ impl<'a, W> Primitive<'a, W> {
None None
} }
pub fn tagged_next(&self) -> Option<TaggedIndex> { pub fn tagged_next(&self) -> Option<Index> {
self.next_node() self.next_node()
.map(|ni| self.graph.node_weight(ni).unwrap().retag(ni)) .map(|ni| self.graph.node_weight(ni).unwrap().retag(ni))
} }
fn next_node(&self) -> Option<NodeIndex<usize>> { fn next_node(&self) -> Option<NodeIndex<usize>> {
self.graph self.graph
.neighbors_directed(self.index.index, Outgoing) .neighbors_directed(self.index.node_index(), Outgoing)
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_end() .is_end()
}) })
@ -147,10 +134,10 @@ impl<'a, W> Primitive<'a, W> {
pub fn core(&self) -> Option<DotIndex> { pub fn core(&self) -> Option<DotIndex> {
self.graph self.graph
.neighbors(self.index.index) .neighbors(self.index.node_index())
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_core() .is_core()
}) })
@ -158,7 +145,7 @@ impl<'a, W> Primitive<'a, W> {
.next() .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 this = self.net(&self.index);
let other = self.net(&index); let other = self.net(&index);
@ -173,46 +160,46 @@ impl<'a, W> Primitive<'a, W> {
} }
} }
fn net<WW>(&self, index: &Index<WW>) -> i64 { fn net<WW>(&self, index: &GenericIndex<WW>) -> i64 {
match self.graph.node_weight(index.index).unwrap() { match self.graph.node_weight(index.node_index()).unwrap() {
Weight::Dot(dot) => dot.net, Weight::Dot(dot) => dot.net,
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) -> TaggedIndex { pub fn tagged_index(&self) -> Index {
self.graph self.graph
.node_weight(self.index.index) .node_weight(self.index.node_index())
.unwrap() .unwrap()
.retag(self.index.index) .retag(self.index.node_index())
} }
pub fn tagged_weight(&self) -> Weight { 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> { fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> {
Primitive::new(index, &self.graph) GenericPrimitive::new(index, &self.graph)
} }
} }
impl<'a, W> Interior<TaggedIndex> for Primitive<'a, W> { impl<'a, W> Interior<Index> for GenericPrimitive<'a, W> {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<Index> {
vec![self.tagged_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) { fn ends(&self) -> (DotIndex, DotIndex) {
let v = self let v = self
.graph .graph
.neighbors_undirected(self.index.index) .neighbors_undirected(self.index.node_index())
.filter(|ni| { .filter(|ni| {
self.graph self.graph
.edge_weight( .edge_weight(
self.graph self.graph
.find_edge_undirected(self.index.index, *ni) .find_edge_undirected(self.index.node_index(), *ni)
.unwrap() .unwrap()
.0, .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> { impl<'a> Dot<'a> {
pub fn bend(&self) -> Option<BendIndex> { pub fn bend(&self) -> Option<BendIndex> {
self.graph self.graph
.neighbors_undirected(self.index.index) .neighbors_undirected(self.index.node_index())
.filter(|ni| { .filter(|ni| {
self.graph self.graph
.edge_weight( .edge_weight(
self.graph self.graph
.find_edge_undirected(self.index.index, *ni) .find_edge_undirected(self.index.node_index(), *ni)
.unwrap() .unwrap()
.0, .0,
) )
@ -250,10 +237,10 @@ impl<'a> Dot<'a> {
pub fn outer(&self) -> Option<BendIndex> { pub fn outer(&self) -> Option<BendIndex> {
self.graph self.graph
.neighbors_directed(self.index.index, Incoming) .neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_core() .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> { impl<'a> Seg<'a> {
pub fn next(&self) -> Option<DotIndex> { 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> { impl<'a> Bend<'a> {
pub fn around(&self) -> TaggedIndex { pub fn around(&self) -> Index {
if let Some(inner) = self.inner() { if let Some(inner) = self.inner() {
TaggedIndex::Bend(inner) Index::Bend(inner)
} else { } else {
TaggedIndex::Dot(self.core().unwrap()) Index::Dot(self.core().unwrap())
} }
} }
pub fn inner(&self) -> Option<BendIndex> { pub fn inner(&self) -> Option<BendIndex> {
self.graph self.graph
.neighbors_directed(self.index.index, Incoming) .neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_outer() .is_outer()
}) })
@ -328,10 +315,10 @@ impl<'a> Bend<'a> {
pub fn outer(&self) -> Option<BendIndex> { pub fn outer(&self) -> Option<BendIndex> {
self.graph self.graph
.neighbors_directed(self.index.index, Outgoing) .neighbors_directed(self.index.node_index(), Outgoing)
.filter(|ni| { .filter(|ni| {
self.graph 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() .unwrap()
.is_outer() .is_outer()
}) })
@ -351,6 +338,27 @@ impl<'a> Bend<'a> {
self.tagged_weight().into_bend().unwrap() 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 { pub fn cross_product(&self) -> f64 {
let center = self.primitive(self.core().unwrap()).weight().circle.pos; let center = self.primitive(self.core().unwrap()).weight().circle.pos;
let ends = self.ends(); let ends = self.ends();

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, Weight}, graph::{BendIndex, DotIndex, Ends, Index, Interior, Label, SegIndex, Weight},
primitive::{Bend, Dot}, primitive::{Bend, Dot},
}; };
@ -46,12 +46,12 @@ impl Segbend {
} }
} }
impl Interior<TaggedIndex> for Segbend { impl Interior<Index> for Segbend {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<Index> {
vec![ vec![
TaggedIndex::Bend(self.bend), Index::Bend(self.bend),
TaggedIndex::Dot(self.dot), Index::Dot(self.dot),
TaggedIndex::Seg(self.seg), Index::Seg(self.seg),
] ]
} }
} }