geometry,primitive: move first rail, core, inner, outer to `Geometry`

This commit is contained in:
Mikolaj Wielgus 2024-01-28 18:25:02 +00:00
parent 4bb513ee08
commit 4c3d0062b0
4 changed files with 142 additions and 106 deletions

View File

@ -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<Shape, GeometryIndex>;
@ -77,7 +78,16 @@ pub struct AlreadyConnected(pub i64, pub GeometryIndex);
pub struct Layout {
rtree: RTree<RTreeWrapper>,
connectivity: ConnectivityGraph,
geometry: Geometry<GeometryWeight, DotWeight, BendWeight, DotIndex, SegIndex, BendIndex>,
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<GeometryWeight, DotWeight, BendWeight, DotIndex, SegIndex, BendIndex> {
) -> &Geometry<
GeometryWeight,
DotWeight,
SegWeight,
BendWeight,
GeometryIndex,
DotIndex,
SegIndex,
BendIndex,
> {
&self.geometry
}

View File

@ -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<GeometryIndex> {
fn retag(&self, index: NodeIndex<usize>) -> 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<GeometryIndex> for $weight_struct {
fn retag(&self, index: NodeIndex<usize>) -> 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<GeometryIndex>)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GeometryWeight {
FixedDot(FixedDotWeight),
@ -148,37 +148,45 @@ pub trait BendWeightTrait<GW>: GetOffset + GetWidth + Into<GW> + Copy {}
#[derive(Debug)]
pub struct Geometry<
GW: GetWidth + TryInto<DW> + TryInto<BW> + Copy,
DW: DotWeightTrait<GW>,
BW: BendWeightTrait<GW>,
DI: GetNodeIndex,
SI: GetNodeIndex,
BI: GetNodeIndex,
GW: GetWidth + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<GI> + Copy,
DW: DotWeightTrait<GW> + Copy,
SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + Copy,
DI: GetNodeIndex + Copy,
SI: GetNodeIndex + Copy,
BI: GetNodeIndex + Copy,
> {
pub graph: StableDiGraph<GW, GeometryLabel, usize>,
weight_marker: PhantomData<GW>,
dot_weight_marker: PhantomData<DW>,
seg_weight_marker: PhantomData<SW>,
bend_weight_marker: PhantomData<BW>,
index_marker: PhantomData<GI>,
dot_index_marker: PhantomData<DI>,
seg_index_marker: PhantomData<SI>,
bend_index_marker: PhantomData<BI>,
}
impl<
GW: GetWidth + TryInto<DW> + TryInto<BW> + Copy,
DW: DotWeightTrait<GW>,
BW: BendWeightTrait<GW>,
GW: GetWidth + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<GI> + Copy,
DW: DotWeightTrait<GW> + Copy,
SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + Copy,
DI: GetNodeIndex + Copy,
SI: GetNodeIndex + Copy,
BI: GetNodeIndex + Copy,
> Geometry<GW, DW, BW, DI, SI, BI>
> Geometry<GW, DW, SW, BW, GI, DI, SI, BI>
{
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<usize>) -> Option<NodeIndex<usize>> {
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<usize>) -> 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<usize>) -> Option<NodeIndex<usize>> {
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<usize>) -> Option<NodeIndex<usize>> {
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<usize>) -> Option<NodeIndex<usize>> {
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<usize>) -> Option<NodeIndex<usize>> {
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<GW, GeometryLabel, usize> {
&self.graph
}

View File

@ -31,6 +31,39 @@ impl From<SegIndex> for GeometryIndex {
}
}
#[enum_dispatch(GetWidth)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SegWeight {
Fixed(FixedSegWeight),
LoneLoose(LoneLooseSegWeight),
SeqLoose(SeqLooseSegWeight),
}
impl From<SegWeight> 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<GeometryWeight> for SegWeight {
type Error = (); // TODO.
fn try_from(weight: GeometryWeight) -> Result<SegWeight, ()> {
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<GeometryWeight> for SegWeight {}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedSegWeight {
pub component: ComponentIndex,

View File

@ -87,26 +87,8 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
fn first_rail(&self) -> Option<LooseBendIndex> {
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<LooseBendIndex> {
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<LooseBendIndex> {
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()
}
}