diff --git a/src/layout.rs b/src/layout.rs index 5bcbf06..d9ffcb1 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -44,6 +44,7 @@ use crate::shape::{Shape, ShapeTrait}; use crate::wraparoundable::{GetWraparound, Wraparoundable, WraparoundableIndex}; use self::bend::BendWeight; +use self::seg::SegWeight; pub type RTreeWrapper = GeomWithData; @@ -77,7 +78,16 @@ pub struct AlreadyConnected(pub i64, pub GeometryIndex); pub struct Layout { rtree: RTree, connectivity: ConnectivityGraph, - geometry: Geometry, + geometry: Geometry< + GeometryWeight, + DotWeight, + SegWeight, + BendWeight, + GeometryIndex, + DotIndex, + SegIndex, + BendIndex, + >, } #[debug_invariant(self.geometry.graph().node_count() == self.rtree.size())] @@ -957,7 +967,16 @@ impl Layout { #[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))] pub fn geometry( &self, - ) -> &Geometry { + ) -> &Geometry< + GeometryWeight, + DotWeight, + SegWeight, + BendWeight, + GeometryIndex, + DotIndex, + SegIndex, + BendIndex, + > { &self.geometry } diff --git a/src/layout/geometry.rs b/src/layout/geometry.rs index 97d2f4a..8bff261 100644 --- a/src/layout/geometry.rs +++ b/src/layout/geometry.rs @@ -4,7 +4,7 @@ use enum_dispatch::enum_dispatch; use geo::Point; use petgraph::{ stable_graph::{NodeIndex, StableDiGraph}, - Direction::Incoming, + Direction::{Incoming, Outgoing}, }; use crate::{ @@ -26,7 +26,7 @@ use super::{ }; #[enum_dispatch] -pub trait Retag { +pub trait Retag { fn retag(&self, index: NodeIndex) -> GeometryIndex; } @@ -60,7 +60,7 @@ pub trait GetOffset { macro_rules! impl_weight { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { - impl Retag for $weight_struct { + impl Retag for $weight_struct { fn retag(&self, index: NodeIndex) -> GeometryIndex { GeometryIndex::$weight_variant($index_struct::new(index)) } @@ -106,7 +106,7 @@ macro_rules! impl_loose_weight { }; } -#[enum_dispatch(GetWidth, Retag)] +#[enum_dispatch(GetWidth, Retag)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum GeometryWeight { FixedDot(FixedDotWeight), @@ -148,37 +148,45 @@ pub trait BendWeightTrait: GetOffset + GetWidth + Into + Copy {} #[derive(Debug)] pub struct Geometry< - GW: GetWidth + TryInto + TryInto + Copy, - DW: DotWeightTrait, - BW: BendWeightTrait, - DI: GetNodeIndex, - SI: GetNodeIndex, - BI: GetNodeIndex, + GW: GetWidth + TryInto + TryInto + TryInto + Retag + Copy, + DW: DotWeightTrait + Copy, + SW: SegWeightTrait + Copy, + BW: BendWeightTrait + Copy, + GI: GetNodeIndex + Copy, + DI: GetNodeIndex + Copy, + SI: GetNodeIndex + Copy, + BI: GetNodeIndex + Copy, > { pub graph: StableDiGraph, weight_marker: PhantomData, dot_weight_marker: PhantomData, + seg_weight_marker: PhantomData, bend_weight_marker: PhantomData, + index_marker: PhantomData, dot_index_marker: PhantomData, seg_index_marker: PhantomData, bend_index_marker: PhantomData, } impl< - GW: GetWidth + TryInto + TryInto + Copy, - DW: DotWeightTrait, - BW: BendWeightTrait, + GW: GetWidth + TryInto + TryInto + TryInto + Retag + Copy, + DW: DotWeightTrait + Copy, + SW: SegWeightTrait + Copy, + BW: BendWeightTrait + Copy, + GI: GetNodeIndex + Copy, DI: GetNodeIndex + Copy, SI: GetNodeIndex + Copy, BI: GetNodeIndex + Copy, - > Geometry + > Geometry { pub fn new() -> Self { Self { graph: StableDiGraph::default(), weight_marker: PhantomData, dot_weight_marker: PhantomData, + seg_weight_marker: PhantomData, bend_weight_marker: PhantomData, + index_marker: PhantomData, dot_index_marker: PhantomData, seg_index_marker: PhantomData, bend_index_marker: PhantomData, @@ -273,20 +281,6 @@ impl< self.core_weight(bend).width() / 2.0 + r } - fn inner(&self, index: NodeIndex) -> Option> { - self.graph - .neighbors_directed(index, Incoming) - .filter(|node| { - matches!( - self.graph - .edge_weight(self.graph.find_edge(*node, index).unwrap()) - .unwrap(), - GeometryLabel::Outer - ) - }) - .next() - } - fn weight(&self, index: NodeIndex) -> GW { *self.graph.node_weight(index).unwrap() } @@ -297,6 +291,12 @@ impl< .unwrap_or_else(|_| unreachable!()) } + fn seg_weight(&self, seg: SI) -> SW { + self.weight(seg.node_index()) + .try_into() + .unwrap_or_else(|_| unreachable!()) + } + fn bend_weight(&self, bend: BI) -> BW { self.weight(bend.node_index()) .try_into() @@ -342,6 +342,62 @@ impl< .unwrap() } + pub fn first_rail(&self, index: NodeIndex) -> Option> { + self.graph + .neighbors_directed(index, Incoming) + .filter(|node| { + matches!( + self.graph + .edge_weight(self.graph.find_edge(*node, index).unwrap()) + .unwrap(), + GeometryLabel::Core + ) + }) + .next() + } + + pub fn core(&self, index: NodeIndex) -> Option> { + self.graph + .neighbors(index) + .filter(|node| { + matches!( + self.graph + .edge_weight(self.graph.find_edge(index, *node).unwrap()) + .unwrap(), + GeometryLabel::Core + ) + }) + .next() + } + + pub fn inner(&self, index: NodeIndex) -> Option> { + self.graph + .neighbors_directed(index, Incoming) + .filter(|node| { + matches!( + self.graph + .edge_weight(self.graph.find_edge(*node, index).unwrap()) + .unwrap(), + GeometryLabel::Outer + ) + }) + .next() + } + + pub fn outer(&self, index: NodeIndex) -> Option> { + self.graph + .neighbors_directed(index, Outgoing) + .filter(|node| { + matches!( + self.graph + .edge_weight(self.graph.find_edge(index, *node).unwrap()) + .unwrap(), + GeometryLabel::Outer + ) + }) + .next() + } + pub fn graph(&self) -> &StableDiGraph { &self.graph } diff --git a/src/layout/seg.rs b/src/layout/seg.rs index 4cf18d2..78a3f45 100644 --- a/src/layout/seg.rs +++ b/src/layout/seg.rs @@ -31,6 +31,39 @@ impl From for GeometryIndex { } } +#[enum_dispatch(GetWidth)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum SegWeight { + Fixed(FixedSegWeight), + LoneLoose(LoneLooseSegWeight), + SeqLoose(SeqLooseSegWeight), +} + +impl From for GeometryWeight { + fn from(seg: SegWeight) -> Self { + match seg { + SegWeight::Fixed(weight) => GeometryWeight::FixedSeg(weight), + SegWeight::LoneLoose(weight) => GeometryWeight::LoneLooseSeg(weight), + SegWeight::SeqLoose(weight) => GeometryWeight::SeqLooseSeg(weight), + } + } +} + +impl TryFrom for SegWeight { + type Error = (); // TODO. + + fn try_from(weight: GeometryWeight) -> Result { + match weight { + GeometryWeight::FixedSeg(weight) => Ok(SegWeight::Fixed(weight)), + GeometryWeight::LoneLooseSeg(weight) => Ok(SegWeight::LoneLoose(weight)), + GeometryWeight::SeqLooseSeg(weight) => Ok(SegWeight::SeqLoose(weight)), + _ => unreachable!(), + } + } +} + +impl SegWeightTrait for SegWeight {} + #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedSegWeight { pub component: ComponentIndex, diff --git a/src/primitive.rs b/src/primitive.rs index beb5882..c68d8c6 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -87,26 +87,8 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex { fn first_rail(&self) -> Option { self.layout() .geometry() - .graph() - .neighbors_directed(self.node_index(), Incoming) - .filter(|node| { - matches!( - self.layout() - .geometry() - .graph() - .edge_weight( - self.layout() - .geometry() - .graph() - .find_edge(*node, self.node_index()) - .unwrap() - ) - .unwrap(), - GeometryLabel::Core - ) - }) + .first_rail(self.node_index()) .map(|node| LooseBendIndex::new(node)) - .next() } } @@ -114,26 +96,8 @@ pub trait GetCore: GetLayout + GetNodeIndex { fn core(&self) -> FixedDotIndex { self.layout() .geometry() - .graph() - .neighbors(self.node_index()) - .filter(|node| { - matches!( - self.layout() - .geometry() - .graph() - .edge_weight( - self.layout() - .geometry() - .graph() - .find_edge(self.node_index(), *node) - .unwrap() - ) - .unwrap(), - GeometryLabel::Core - ) - }) + .core(self.node_index()) .map(|node| FixedDotIndex::new(node)) - .next() .unwrap() } } @@ -142,51 +106,15 @@ pub trait GetInnerOuter: GetLayout + GetNodeIndex { fn inner(&self) -> Option { self.layout() .geometry() - .graph() - .neighbors_directed(self.node_index(), Incoming) - .filter(|node| { - matches!( - self.layout() - .geometry() - .graph() - .edge_weight( - self.layout() - .geometry() - .graph() - .find_edge(*node, self.node_index()) - .unwrap() - ) - .unwrap(), - GeometryLabel::Outer - ) - }) + .inner(self.node_index()) .map(|node| LooseBendIndex::new(node)) - .next() } fn outer(&self) -> Option { self.layout() .geometry() - .graph() - .neighbors_directed(self.node_index(), Outgoing) - .filter(|node| { - matches!( - self.layout() - .geometry() - .graph() - .edge_weight( - self.layout() - .geometry() - .graph() - .find_edge(self.node_index(), *node) - .unwrap() - ) - .unwrap(), - GeometryLabel::Outer - ) - }) + .outer(self.node_index()) .map(|node| LooseBendIndex::new(node)) - .next() } }