mirror of https://codeberg.org/topola/topola.git
graph,primitive: Use enum_dispatch, rely on generics less
This commit is contained in:
parent
4e21ff754d
commit
708fbb98f1
22
src/band.rs
22
src/band.rs
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
16
src/bow.rs
16
src/bow.rs
|
|
@ -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),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
src/draw.rs
20
src/draw.rs
|
|
@ -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 {
|
||||
|
|
|
|||
70
src/graph.rs
70
src/graph.rs
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
132
src/layout.rs
132
src/layout.rs
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
142
src/primitive.rs
142
src/primitive.rs
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue