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 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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
src/bow.rs
16
src/bow.rs
|
|
@ -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),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/draw.rs
20
src/draw.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
70
src/graph.rs
70
src/graph.rs
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
132
src/layout.rs
132
src/layout.rs
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
142
src/primitive.rs
142
src/primitive.rs
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue