geometry: use narrower types for returned adjacents

This commit is contained in:
Mikolaj Wielgus 2024-01-28 20:53:36 +00:00
parent 4c3d0062b0
commit 87705653bd
5 changed files with 119 additions and 26 deletions

View File

@ -30,6 +30,18 @@ impl From<BendIndex> for GeometryIndex {
}
}
impl TryFrom<GeometryIndex> for BendIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<BendIndex, ()> {
match index {
GeometryIndex::FixedBend(index) => Ok(BendIndex::Fixed(index)),
GeometryIndex::LooseBend(index) => Ok(BendIndex::Loose(index)),
_ => unreachable!(),
}
}
}
#[enum_dispatch(GetOffset, GetWidth)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BendWeight {

View File

@ -31,6 +31,18 @@ impl From<DotIndex> for GeometryIndex {
}
}
impl TryFrom<GeometryIndex> for DotIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<DotIndex, ()> {
match index {
GeometryIndex::FixedDot(index) => Ok(DotIndex::Fixed(index)),
GeometryIndex::LooseDot(index) => Ok(DotIndex::Loose(index)),
_ => unreachable!(),
}
}
}
#[enum_dispatch(GetPos, GetWidth)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DotWeight {

View File

@ -152,7 +152,7 @@ pub struct Geometry<
DW: DotWeightTrait<GW> + Copy,
SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + Copy,
GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy,
DI: GetNodeIndex + Copy,
SI: GetNodeIndex + Copy,
BI: GetNodeIndex + Copy,
@ -173,7 +173,7 @@ impl<
DW: DotWeightTrait<GW> + Copy,
SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + Copy,
GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy,
DI: GetNodeIndex + Copy,
SI: GetNodeIndex + Copy,
BI: GetNodeIndex + Copy,
@ -267,11 +267,11 @@ impl<
fn inner_radius(&self, bend: BI) -> f64 {
let mut r = self.bend_weight(bend).offset();
let mut rail = bend.node_index();
let mut rail = bend;
while let Some(inner) = self.inner(rail) {
let weight: BW = self
.weight(inner)
.bend_weight(inner)
.try_into()
.unwrap_or_else(|_| unreachable!());
r += weight.width() + weight.offset();
@ -342,7 +342,7 @@ impl<
.unwrap()
}
pub fn first_rail(&self, index: NodeIndex<usize>) -> Option<NodeIndex<usize>> {
pub fn first_rail(&self, index: NodeIndex<usize>) -> Option<BI> {
self.graph
.neighbors_directed(index, Incoming)
.filter(|node| {
@ -353,48 +353,81 @@ impl<
GeometryLabel::Core
)
})
.map(|node| {
self.graph
.node_weight(node)
.unwrap()
.retag(node)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
.next()
}
pub fn core(&self, index: NodeIndex<usize>) -> Option<NodeIndex<usize>> {
pub fn core(&self, bend: BI) -> DI {
self.graph
.neighbors(index)
.neighbors(bend.node_index())
.filter(|node| {
matches!(
self.graph
.edge_weight(self.graph.find_edge(index, *node).unwrap())
.edge_weight(self.graph.find_edge(bend.node_index(), *node).unwrap())
.unwrap(),
GeometryLabel::Core
)
})
.map(|node| {
self.graph
.node_weight(node)
.unwrap()
.retag(node)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
.next()
.unwrap()
}
pub fn inner(&self, index: NodeIndex<usize>) -> Option<NodeIndex<usize>> {
pub fn inner(&self, bend: BI) -> Option<BI> {
self.graph
.neighbors_directed(index, Incoming)
.neighbors_directed(bend.node_index(), Incoming)
.filter(|node| {
matches!(
self.graph
.edge_weight(self.graph.find_edge(*node, index).unwrap())
.edge_weight(self.graph.find_edge(*node, bend.node_index()).unwrap())
.unwrap(),
GeometryLabel::Outer
)
})
.map(|node| {
self.graph
.node_weight(node)
.unwrap()
.retag(node)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
.next()
}
pub fn outer(&self, index: NodeIndex<usize>) -> Option<NodeIndex<usize>> {
pub fn outer(&self, bend: BI) -> Option<BI> {
self.graph
.neighbors_directed(index, Outgoing)
.neighbors_directed(bend.node_index(), Outgoing)
.filter(|node| {
matches!(
self.graph
.edge_weight(self.graph.find_edge(index, *node).unwrap())
.edge_weight(self.graph.find_edge(bend.node_index(), *node).unwrap())
.unwrap(),
GeometryLabel::Outer
)
})
.map(|node| {
self.graph
.node_weight(node)
.unwrap()
.retag(node)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
.next()
}

View File

@ -31,6 +31,19 @@ impl From<SegIndex> for GeometryIndex {
}
}
impl TryFrom<GeometryIndex> for SegIndex {
type Error = (); // TODO.
fn try_from(index: GeometryIndex) -> Result<SegIndex, ()> {
match index {
GeometryIndex::FixedSeg(index) => Ok(SegIndex::Fixed(index)),
GeometryIndex::LoneLooseSeg(index) => Ok(SegIndex::LoneLoose(index)),
GeometryIndex::SeqLooseSeg(index) => Ok(SegIndex::SeqLoose(index)),
_ => unreachable!(),
}
}
}
#[enum_dispatch(GetWidth)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SegWeight {

View File

@ -88,33 +88,38 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
self.layout()
.geometry()
.first_rail(self.node_index())
.map(|node| LooseBendIndex::new(node))
.map(|node| LooseBendIndex::new(node.node_index()))
}
}
pub trait GetCore: GetLayout + GetNodeIndex {
pub trait GetBendIndex {
fn bend_index(&self) -> BendIndex;
}
pub trait GetCore: GetLayout + GetBendIndex {
fn core(&self) -> FixedDotIndex {
FixedDotIndex::new(
self.layout()
.geometry()
.core(self.node_index())
.map(|node| FixedDotIndex::new(node))
.unwrap()
.core(self.bend_index())
.node_index(),
)
}
}
pub trait GetInnerOuter: GetLayout + GetNodeIndex {
pub trait GetInnerOuter: GetLayout + GetBendIndex {
fn inner(&self) -> Option<LooseBendIndex> {
self.layout()
.geometry()
.inner(self.node_index())
.map(|node| LooseBendIndex::new(node))
.inner(self.bend_index())
.map(|node| LooseBendIndex::new(node.node_index()))
}
fn outer(&self) -> Option<LooseBendIndex> {
self.layout()
.geometry()
.outer(self.node_index())
.map(|node| LooseBendIndex::new(node))
.outer(self.bend_index())
.map(|node| LooseBendIndex::new(node.node_index()))
}
}
@ -446,6 +451,12 @@ impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {}
pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>;
impl_fixed_primitive!(FixedBend, FixedBendWeight);
impl<'a> GetBendIndex for FixedBend<'a> {
fn bend_index(&self) -> BendIndex {
self.index.into()
}
}
impl<'a> MakeShape for FixedBend<'a> {
fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into())
@ -469,6 +480,18 @@ impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actu
pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>;
impl_loose_primitive!(LooseBend, LooseBendWeight);
impl<'a> GetBendIndex for LooseBend<'a> {
fn bend_index(&self) -> BendIndex {
self.index.into()
}
}
impl<'a> From<LooseBend<'a>> for BendIndex {
fn from(bend: LooseBend<'a>) -> BendIndex {
bend.index.into()
}
}
impl<'a> MakeShape for LooseBend<'a> {
fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into())