band,bow: Remove unused band, bow modules, add new traverser module

Implement a traverser for wrapped bends.
This commit is contained in:
Mikolaj Wielgus 2023-11-01 20:16:11 +00:00
parent 9a5b046724
commit a6481cb839
6 changed files with 89 additions and 162 deletions

View File

@ -1,68 +0,0 @@
use crate::graph::{FixedDotIndex, GetEnds, Index, Interior};
pub struct Band {
from: FixedDotIndex,
to: FixedDotIndex,
interior: Vec<Index>,
}
/*impl Band {
pub fn from_dot_prev(
dot: FixedDotIndex,
graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> {
let mut next_index: Index = dot.into();
let mut interior = vec![];
while let Some(index) = next_index.primitive(graph).tagged_prev() {
interior.push(index);
next_index = index;
}
if interior.is_empty() {
None
} else {
Some(Self {
from: interior.pop().unwrap().into_fixed_dot().unwrap(),
to: dot,
interior,
})
}
}
pub fn from_dot_next(
dot: FixedDotIndex,
graph: &StableDiGraph<Weight, Label, usize>,
) -> Option<Self> {
let mut prev_index: Index = dot.into();
let mut interior = vec![];
while let Some(index) = prev_index.primitive(graph).tagged_next() {
interior.push(index);
prev_index = index;
}
if interior.is_empty() {
None
} else {
Some(Self {
from: dot,
to: interior.pop().unwrap().into_fixed_dot().unwrap(),
interior,
})
}
}
}*/
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()
}
}
impl GetEnds<FixedDotIndex, FixedDotIndex> for Band {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) {
(self.from, self.to)
}
}

View File

@ -1,54 +0,0 @@
use crate::graph::{GetEnds, Index, Interior, LooseBendIndex, LooseDotIndex, LooseSegIndex};
#[derive(Debug, Clone, Copy)]
pub struct Bow {
seg1_dot1: LooseDotIndex,
seg1: LooseSegIndex,
seg1_dot2: LooseDotIndex,
bend: LooseBendIndex,
seg2_dot1: LooseDotIndex,
seg2: LooseSegIndex,
seg2_dot2: LooseDotIndex,
}
/*impl Bow {
pub fn from_bend(index: LooseBendIndex, graph: &StableDiGraph<Weight, Label, usize>) -> Self {
let bend = index;
let seg1_dot2 = LooseBend::new(bend, graph).ends().0;
let seg1 = LooseDot::new(seg1_dot2, graph).seg().unwrap();
let seg1_dot1 = LooseSeg::new(seg1, graph).other_end(seg1_dot2);
let seg2_dot1 = LooseBend::new(bend, graph).ends().1;
let seg2 = LooseDot::new(seg2_dot1, graph).seg().unwrap();
let seg2_dot2 = LooseSeg::new(seg2, graph).other_end(seg2_dot1);
Self {
seg1_dot1,
seg1,
seg1_dot2,
bend,
seg2_dot1,
seg2,
seg2_dot2,
}
}
}*/
impl Interior<Index> for Bow {
fn interior(&self) -> Vec<Index> {
vec![
self.seg1.into(),
self.seg1_dot2.into(),
self.bend.into(),
self.seg2_dot1.into(),
self.seg2.into(),
]
}
}
impl GetEnds<LooseDotIndex, LooseDotIndex> for Bow {
fn ends(&self) -> (LooseDotIndex, LooseDotIndex) {
(self.seg1_dot1, self.seg2_dot2)
}
}

View File

@ -11,8 +11,6 @@ macro_rules! dbg_dot {
#[macro_use] #[macro_use]
mod graph; mod graph;
mod astar; mod astar;
mod band;
mod bow;
mod draw; mod draw;
mod guide; mod guide;
mod layout; mod layout;
@ -24,6 +22,7 @@ mod rules;
mod segbend; mod segbend;
mod shape; mod shape;
mod tracer; mod tracer;
mod traverser;
use geo::point; use geo::point;
use graph::{FixedDotIndex, FixedSegWeight, LooseDotIndex}; use graph::{FixedDotIndex, FixedSegWeight, LooseDotIndex};

View File

@ -4,9 +4,8 @@ use geo::{point, Point};
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use petgraph::visit::{self, NodeIndexable}; use petgraph::visit::{self, NodeIndexable};
use spade::{ use spade::{
handles::{DirectedEdgeHandle, FixedDirectedEdgeHandle, FixedVertexHandle}, handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError, Point2,
iterators::DirectedEdgeIterator, Triangulation,
DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation,
}; };
use crate::{ use crate::{

View File

@ -12,6 +12,7 @@ use crate::graph::{
}; };
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};
use crate::traverser::OutwardLayerTraverser;
#[enum_dispatch] #[enum_dispatch]
pub trait GetGraph { pub trait GetGraph {
@ -49,6 +50,42 @@ pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
} }
} }
pub trait TraverseOutward: GetFirstLayer {
fn traverse_outward(&self) -> OutwardLayerTraverser {
OutwardLayerTraverser::new(self.first_layer(), self.graph())
}
}
pub trait GetFirstLayer: GetGraph + GetNodeIndex {
fn first_layer(&self) -> Option<LooseBendIndex> {
self.graph()
.neighbors_directed(self.node_index(), Incoming)
.filter(|ni| {
self.graph()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap())
.unwrap()
.is_core()
})
.map(|ni| LooseBendIndex::new(ni))
.next()
}
}
pub trait GetOuter: GetGraph + GetNodeIndex {
fn outer(&self) -> Option<LooseBendIndex> {
self.graph()
.neighbors_directed(self.node_index(), Outgoing)
.filter(|ni| {
self.graph()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap())
.unwrap()
.is_outer()
})
.map(|ni| LooseBendIndex::new(ni))
.next()
}
}
#[enum_dispatch(GetNet, GetWidth, GetGraph, GetConnectable, MakeShape)] #[enum_dispatch(GetNet, GetWidth, GetGraph, GetConnectable, MakeShape)]
pub enum Primitive<'a> { pub enum Primitive<'a> {
FixedDot(FixedDot<'a>), FixedDot(FixedDot<'a>),
@ -70,12 +107,6 @@ impl<'a, W> GenericPrimitive<'a, W> {
Self { index, graph } Self { index, graph }
} }
pub fn neighbors(&self) -> impl Iterator<Item = Index> + '_ {
self.graph
.neighbors_undirected(self.index.node_index())
.map(|index| self.graph.node_weight(index).unwrap().retag(index))
}
pub fn core(&self) -> Option<FixedDotIndex> { pub fn core(&self) -> Option<FixedDotIndex> {
self.graph self.graph
.neighbors(self.index.node_index()) .neighbors(self.index.node_index())
@ -127,6 +158,12 @@ impl<'a, W> GetGraph for GenericPrimitive<'a, W> {
} }
} }
impl<'a, W> GetNodeIndex for GenericPrimitive<'a, W> {
fn node_index(&self) -> NodeIndex<usize> {
self.index.node_index()
}
}
impl<'a, W: GetNet> GetConnectable for GenericPrimitive<'a, W> where impl<'a, W: GetNet> GetConnectable for GenericPrimitive<'a, W> where
GenericPrimitive<'a, W>: GetWeight<W> GenericPrimitive<'a, W>: GetWeight<W>
{ {
@ -152,22 +189,6 @@ where
pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>; pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>;
impl<'a> FixedDot<'a> {
pub fn outer(&self) -> Option<FixedBendIndex> {
self.graph
.neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap())
.unwrap()
.is_core()
})
.map(|ni| FixedBendIndex::new(ni))
.filter(|bend| self.primitive(*bend).inner().is_none())
.next()
}
}
impl<'a> GetWeight<FixedDotWeight> for FixedDot<'a> { impl<'a> GetWeight<FixedDotWeight> for FixedDot<'a> {
fn weight(&self) -> FixedDotWeight { fn weight(&self) -> FixedDotWeight {
self.tagged_weight().into_fixed_dot().unwrap() self.tagged_weight().into_fixed_dot().unwrap()
@ -182,6 +203,10 @@ impl<'a> MakeShape for FixedDot<'a> {
} }
} }
impl<'a> TraverseOutward for FixedDot<'a> {}
impl<'a> GetFirstLayer for FixedDot<'a> {}
pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>; pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>;
impl<'a> LooseDot<'a> { impl<'a> LooseDot<'a> {
@ -334,19 +359,6 @@ impl<'a> FixedBend<'a> {
.next() .next()
} }
pub fn outer(&self) -> Option<FixedBendIndex> {
self.graph
.neighbors_directed(self.index.node_index(), Outgoing)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(self.index.node_index(), *ni).unwrap())
.unwrap()
.is_outer()
})
.map(|ni| FixedBendIndex::new(ni))
.next()
}
fn inner_radius(&self) -> f64 { fn inner_radius(&self) -> f64 {
let mut r = 0.0; let mut r = 0.0;
let mut layer = FixedBendIndex::new(self.index.node_index()); let mut layer = FixedBendIndex::new(self.index.node_index());
@ -413,6 +425,12 @@ impl<'a> GetEnds<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {} impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {}
impl<'a> TraverseOutward for FixedBend<'a> {}
impl<'a> GetFirstLayer for FixedBend<'a> {}
impl<'a> GetOuter for FixedBend<'a> {}
pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>; pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>;
impl<'a> LooseBend<'a> { impl<'a> LooseBend<'a> {
@ -492,3 +510,5 @@ impl<'a> GetEnds<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
} }
impl<'a> GetOtherEnd<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {} impl<'a> GetOtherEnd<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {}
impl<'a> GetOuter for LooseBend<'a> {}

31
src/traverser.rs Normal file
View File

@ -0,0 +1,31 @@
use petgraph::stable_graph::StableDiGraph;
use crate::{
graph::{Label, LooseBendIndex, Weight},
primitive::{GenericPrimitive, GetOuter},
};
pub struct OutwardLayerTraverser<'a> {
layer: Option<LooseBendIndex>,
graph: &'a StableDiGraph<Weight, Label, usize>,
}
impl<'a> OutwardLayerTraverser<'a> {
pub fn new(
layer: Option<LooseBendIndex>,
graph: &'a StableDiGraph<Weight, Label, usize>,
) -> Self {
Self { layer, graph }
}
}
impl<'a> Iterator for OutwardLayerTraverser<'a> {
type Item = LooseBendIndex;
fn next(&mut self) -> Option<Self::Item> {
self.layer.map(|layer| {
self.layer = GenericPrimitive::new(layer, self.graph).outer();
layer
})
}
}