geometry,primitive: move more code and narrow typing further

We replace all instances of `NodeIndex<usize>` in public interfaces of
`Geometry` except for `.first_rail()`, for which we make a dirty
exception.

We also improve terminology a bit:

- "joint" is renamed to "connection",
- "end" is renamed to "joint",
- "leg" is renamed to "limb".
This commit is contained in:
Mikolaj Wielgus 2024-01-28 22:48:54 +00:00
parent 87705653bd
commit 684d0be641
8 changed files with 266 additions and 216 deletions

View File

@ -7,7 +7,7 @@ use crate::{
geometry::{GeometryIndex, MakePrimitive}, geometry::{GeometryIndex, MakePrimitive},
}, },
loose::{GetNextLoose, LooseIndex}, loose::{GetNextLoose, LooseIndex},
primitive::{GetEnds, GetOtherEnd, MakeShape}, primitive::{GetJoints, GetOtherJoint, MakeShape},
shape::ShapeTrait, shape::ShapeTrait,
}; };
@ -52,10 +52,10 @@ impl<'a> Band<'a> {
match prev { match prev {
Some(LooseIndex::LoneSeg(seg)) => { Some(LooseIndex::LoneSeg(seg)) => {
Some(self.layout.primitive(seg).other_end(self.from())) Some(self.layout.primitive(seg).other_joint(self.from()))
} }
Some(LooseIndex::SeqSeg(seg)) => { Some(LooseIndex::SeqSeg(seg)) => {
if let DotIndex::Fixed(dot) = self.layout.primitive(seg).ends().0 { if let DotIndex::Fixed(dot) = self.layout.primitive(seg).joints().0 {
Some(dot) Some(dot)
} else { } else {
None None

View File

@ -12,7 +12,7 @@ use crate::{
}, },
layout::{Infringement, Layout, LayoutException}, layout::{Infringement, Layout, LayoutException},
math::{Circle, NoTangents}, math::{Circle, NoTangents},
primitive::GetOtherEnd, primitive::GetOtherJoint,
rules::{Conditions, Rules}, rules::{Conditions, Rules},
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
}; };
@ -231,7 +231,7 @@ impl<'a> Draw<'a> {
}, },
)?; )?;
Ok::<SegbendHead, LayoutException>(SegbendHead { Ok::<SegbendHead, LayoutException>(SegbendHead {
face: self.layout.primitive(segbend.bend).other_end(segbend.dot), face: self.layout.primitive(segbend.bend).other_joint(segbend.dot),
segbend, segbend,
band: head.band(), band: head.band(),
}) })
@ -243,7 +243,7 @@ impl<'a> Draw<'a> {
let prev_dot = self let prev_dot = self
.layout .layout
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_end(head.segbend.dot.into()); .other_joint(head.segbend.dot.into());
let band = head.band; let band = head.band;
self.layout.remove_segbend(&head.segbend, head.face); self.layout.remove_segbend(&head.segbend, head.face);

View File

@ -10,7 +10,7 @@ use crate::{
geometry::{GetBandIndex, MakePrimitive}, geometry::{GetBandIndex, MakePrimitive},
}, },
math::{self, Circle, NoTangents}, math::{self, Circle, NoTangents},
primitive::{GetCore, GetInnerOuter, GetOtherEnd, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
segbend::Segbend, segbend::Segbend,
shape::{Shape, ShapeTrait}, shape::{Shape, ShapeTrait},
@ -230,6 +230,6 @@ impl<'a, 'b> Guide<'a, 'b> {
fn rear(&self, head: SegbendHead) -> DotIndex { fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout self.layout
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_end(head.segbend.dot.into()) .other_joint(head.segbend.dot.into())
} }
} }

View File

@ -36,7 +36,7 @@ use crate::layout::{
use crate::loose::{GetNextLoose, Loose, LooseIndex}; use crate::loose::{GetNextLoose, Loose, LooseIndex};
use crate::math::NoTangents; use crate::math::NoTangents;
use crate::primitive::{ use crate::primitive::{
GenericPrimitive, GetConnectable, GetCore, GetEnds, GetInnerOuter, GetLegs, GetOtherEnd, GenericPrimitive, GetConnectable, GetCore, GetInnerOuter, GetJoints, GetLimbs, GetOtherJoint,
GetWeight, MakeShape, GetWeight, MakeShape,
}; };
use crate::segbend::Segbend; use crate::segbend::Segbend;
@ -303,7 +303,7 @@ impl Layout {
// Segs must not cross. // Segs must not cross.
if let Some(collision) = self.detect_collision(segbend.seg.into()) { if let Some(collision) = self.detect_collision(segbend.seg.into()) {
let end = self.primitive(segbend.bend).other_end(segbend.dot); let end = self.primitive(segbend.bend).other_joint(segbend.dot);
self.remove_segbend(&segbend, end.into()); self.remove_segbend(&segbend, end.into());
return Err(collision.into()); return Err(collision.into());
} }
@ -375,7 +375,7 @@ impl Layout {
let mut bow: Vec<GeometryIndex> = vec![]; let mut bow: Vec<GeometryIndex> = vec![];
bow.push(bend.into()); bow.push(bend.into());
let ends = self.primitive(bend).ends(); let ends = self.primitive(bend).joints();
bow.push(ends.0.into()); bow.push(ends.0.into());
bow.push(ends.1.into()); bow.push(ends.1.into());
@ -401,7 +401,7 @@ impl Layout {
outer_bows.push(outer.into()); outer_bows.push(outer.into());
let ends = primitive.ends(); let ends = primitive.joints();
outer_bows.push(ends.0.into()); outer_bows.push(ends.0.into());
outer_bows.push(ends.1.into()); outer_bows.push(ends.1.into());
@ -453,7 +453,7 @@ impl Layout {
while let Some(rail) = maybe_rail { while let Some(rail) = maybe_rail {
let primitive = self.primitive(rail); let primitive = self.primitive(rail);
let cw = primitive.weight().cw; let cw = primitive.weight().cw;
let ends = primitive.ends(); let ends = primitive.joints();
let rules = Default::default(); let rules = Default::default();
let conditions = Default::default(); let conditions = Default::default();
@ -843,7 +843,7 @@ impl Layout {
to: Point, to: Point,
infringables: &[GeometryIndex], infringables: &[GeometryIndex],
) -> Result<(), Infringement> { ) -> Result<(), Infringement> {
self.remove_from_rtree_with_legs(dot.into()); self.remove_from_rtree_with_limbs(dot.into());
let mut weight = *self.geometry.graph.node_weight(dot.node_index()).unwrap(); let mut weight = *self.geometry.graph.node_weight(dot.node_index()).unwrap();
let old_weight = weight; let old_weight = weight;
@ -872,11 +872,11 @@ impl Layout {
.node_weight_mut(dot.node_index()) .node_weight_mut(dot.node_index())
.unwrap() = old_weight; .unwrap() = old_weight;
self.insert_into_rtree_with_legs(dot.into()); self.insert_into_rtree_with_limbs(dot.into());
return Err(infringement); return Err(infringement);
} }
self.insert_into_rtree_with_legs(dot.into()); self.insert_into_rtree_with_limbs(dot.into());
Ok(()) Ok(())
} }
@ -922,11 +922,11 @@ impl Layout {
#[debug_ensures(self.geometry.graph().node_count() == old(self.geometry.graph().node_count()))] #[debug_ensures(self.geometry.graph().node_count() == old(self.geometry.graph().node_count()))]
#[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))] #[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))]
fn insert_into_rtree_with_legs(&mut self, node: GeometryIndex) { fn insert_into_rtree_with_limbs(&mut self, node: GeometryIndex) {
self.insert_into_rtree(node); self.insert_into_rtree(node);
for leg in node.primitive(self).legs() { for limb in node.primitive(self).limbs() {
self.insert_into_rtree(leg); self.insert_into_rtree(limb);
} }
} }
@ -939,9 +939,9 @@ impl Layout {
#[debug_ensures(self.geometry.graph().node_count() == old(self.geometry.graph().node_count()))] #[debug_ensures(self.geometry.graph().node_count() == old(self.geometry.graph().node_count()))]
#[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))] #[debug_ensures(self.geometry.graph().edge_count() == old(self.geometry.graph().edge_count()))]
fn remove_from_rtree_with_legs(&mut self, node: GeometryIndex) { fn remove_from_rtree_with_limbs(&mut self, node: GeometryIndex) {
for leg in node.primitive(self).legs() { for limb in node.primitive(self).limbs() {
self.remove_from_rtree(leg); self.remove_from_rtree(limb);
} }
self.remove_from_rtree(node); self.remove_from_rtree(node);

View File

@ -132,7 +132,7 @@ pub enum GeometryIndex {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum GeometryLabel { pub enum GeometryLabel {
Joint, Connection,
Outer, Outer,
Core, Core,
} }
@ -153,9 +153,9 @@ pub struct Geometry<
SW: SegWeightTrait<GW> + Copy, SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy, BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy, GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy,
DI: GetNodeIndex + Copy, DI: GetNodeIndex + Into<GI> + Copy,
SI: GetNodeIndex + Copy, SI: GetNodeIndex + Into<GI> + Copy,
BI: GetNodeIndex + Copy, BI: GetNodeIndex + Into<GI> + Copy,
> { > {
pub graph: StableDiGraph<GW, GeometryLabel, usize>, pub graph: StableDiGraph<GW, GeometryLabel, usize>,
weight_marker: PhantomData<GW>, weight_marker: PhantomData<GW>,
@ -174,9 +174,9 @@ impl<
SW: SegWeightTrait<GW> + Copy, SW: SegWeightTrait<GW> + Copy,
BW: BendWeightTrait<GW> + Copy, BW: BendWeightTrait<GW> + Copy,
GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy, GI: GetNodeIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy,
DI: GetNodeIndex + Copy, DI: GetNodeIndex + Into<GI> + Copy,
SI: GetNodeIndex + Copy, SI: GetNodeIndex + Into<GI> + Copy,
BI: GetNodeIndex + Copy, BI: GetNodeIndex + Into<GI> + Copy,
> Geometry<GW, DW, SW, BW, GI, DI, SI, BI> > Geometry<GW, DW, SW, BW, GI, DI, SI, BI>
{ {
pub fn new() -> Self { pub fn new() -> Self {
@ -205,10 +205,13 @@ impl<
) -> GenericIndex<W> { ) -> GenericIndex<W> {
let seg = GenericIndex::<W>::new(self.graph.add_node(weight.into())); let seg = GenericIndex::<W>::new(self.graph.add_node(weight.into()));
self.graph.update_edge(
from.node_index(),
seg.node_index(),
GeometryLabel::Connection,
);
self.graph self.graph
.update_edge(from.node_index(), seg.node_index(), GeometryLabel::Joint); .update_edge(seg.node_index(), to.node_index(), GeometryLabel::Connection);
self.graph
.update_edge(seg.node_index(), to.node_index(), GeometryLabel::Joint);
seg seg
} }
@ -222,10 +225,16 @@ impl<
) -> GenericIndex<W> { ) -> GenericIndex<W> {
let bend = GenericIndex::<W>::new(self.graph.add_node(weight.into())); let bend = GenericIndex::<W>::new(self.graph.add_node(weight.into()));
self.graph self.graph.update_edge(
.update_edge(from.node_index(), bend.node_index(), GeometryLabel::Joint); from.node_index(),
self.graph bend.node_index(),
.update_edge(bend.node_index(), to.node_index(), GeometryLabel::Joint); GeometryLabel::Connection,
);
self.graph.update_edge(
bend.node_index(),
to.node_index(),
GeometryLabel::Connection,
);
self.graph self.graph
.update_edge(bend.node_index(), core.node_index(), GeometryLabel::Core); .update_edge(bend.node_index(), core.node_index(), GeometryLabel::Core);
@ -243,20 +252,20 @@ impl<
} }
pub fn seg_shape(&self, seg: SI) -> Shape { pub fn seg_shape(&self, seg: SI) -> Shape {
let joint_weights = self.joint_weights(seg.node_index()); let (from, to) = self.seg_joints(seg);
Shape::Seg(SegShape { Shape::Seg(SegShape {
from: joint_weights[0].pos(), from: self.dot_weight(from).pos(),
to: joint_weights[1].pos(), to: self.dot_weight(to).pos(),
width: self.weight(seg.node_index()).width(), width: self.weight(seg.node_index()).width(),
}) })
} }
pub fn bend_shape(&self, bend: BI) -> Shape { pub fn bend_shape(&self, bend: BI) -> Shape {
let joint_weights = self.joint_weights(bend.node_index()); let (from, to) = self.bend_joints(bend);
let core_weight = self.core_weight(bend); let core_weight = self.core_weight(bend);
Shape::Bend(BendShape { Shape::Bend(BendShape {
from: joint_weights[0].pos(), from: self.dot_weight(from).pos(),
to: joint_weights[1].pos(), to: self.dot_weight(to).pos(),
c: Circle { c: Circle {
pos: core_weight.pos(), pos: core_weight.pos(),
r: self.inner_radius(bend), r: self.inner_radius(bend),
@ -285,56 +294,37 @@ impl<
*self.graph.node_weight(index).unwrap() *self.graph.node_weight(index).unwrap()
} }
fn dot_weight(&self, dot: DI) -> DW { pub fn dot_weight(&self, dot: DI) -> DW {
self.weight(dot.node_index()) self.weight(dot.node_index())
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
} }
fn seg_weight(&self, seg: SI) -> SW { pub fn seg_weight(&self, seg: SI) -> SW {
self.weight(seg.node_index()) self.weight(seg.node_index())
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
} }
fn bend_weight(&self, bend: BI) -> BW { pub fn bend_weight(&self, bend: BI) -> BW {
self.weight(bend.node_index()) self.weight(bend.node_index())
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
} }
fn joint_weights(&self, index: NodeIndex<usize>) -> Vec<DW> {
self.graph
.neighbors_undirected(index)
.filter(|node| {
matches!(
self.graph
.edge_weight(self.graph.find_edge_undirected(index, *node).unwrap().0,)
.unwrap(),
GeometryLabel::Joint
)
})
.map(|node| {
self.weight(node)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
.collect()
}
fn core_weight(&self, bend: BI) -> DW { fn core_weight(&self, bend: BI) -> DW {
self.graph self.graph
.neighbors(bend.node_index()) .neighbors(bend.node_index())
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.graph self.graph
.edge_weight(self.graph.find_edge(bend.node_index(), *node).unwrap()) .edge_weight(self.graph.find_edge(bend.node_index(), *ni).unwrap())
.unwrap(), .unwrap(),
GeometryLabel::Core GeometryLabel::Core
) )
}) })
.map(|node| { .map(|ni| {
self.weight(node) self.weight(ni)
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
}) })
@ -342,22 +332,60 @@ impl<
.unwrap() .unwrap()
} }
pub fn first_rail(&self, index: NodeIndex<usize>) -> Option<BI> { pub fn seg_joints(&self, seg: SI) -> (DI, DI) {
let v: Vec<_> = self.connections(seg.into()).collect();
(
v[0].try_into().unwrap_or_else(|_| unreachable!()),
v[1].try_into().unwrap_or_else(|_| unreachable!()),
)
}
pub fn bend_joints(&self, bend: BI) -> (DI, DI) {
let v: Vec<_> = self.connections(bend.into()).collect();
(
v[0].try_into().unwrap_or_else(|_| unreachable!()),
v[1].try_into().unwrap_or_else(|_| unreachable!()),
)
}
pub fn connections(&self, node: GI) -> impl Iterator<Item = GI> + '_ {
self.graph self.graph
.neighbors_directed(index, Incoming) .neighbors_undirected(node.node_index())
.filter(|node| { .filter(move |ni| {
matches!( matches!(
self.graph self.graph
.edge_weight(self.graph.find_edge(*node, index).unwrap()) .edge_weight(
self.graph
.find_edge_undirected(node.node_index(), *ni)
.unwrap()
.0,
)
.unwrap(),
GeometryLabel::Connection
)
})
.map(|ni| {
self.weight(ni)
.retag(ni)
.try_into()
.unwrap_or_else(|_| unreachable!())
})
}
pub fn first_rail(&self, node: NodeIndex<usize>) -> Option<BI> {
self.graph
.neighbors_directed(node, Incoming)
.filter(|ni| {
matches!(
self.graph
.edge_weight(self.graph.find_edge(*ni, node).unwrap())
.unwrap(), .unwrap(),
GeometryLabel::Core GeometryLabel::Core
) )
}) })
.map(|node| { .map(|ni| {
self.graph self.weight(ni)
.node_weight(node) .retag(ni)
.unwrap()
.retag(node)
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
}) })
@ -367,19 +395,17 @@ impl<
pub fn core(&self, bend: BI) -> DI { pub fn core(&self, bend: BI) -> DI {
self.graph self.graph
.neighbors(bend.node_index()) .neighbors(bend.node_index())
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.graph self.graph
.edge_weight(self.graph.find_edge(bend.node_index(), *node).unwrap()) .edge_weight(self.graph.find_edge(bend.node_index(), *ni).unwrap())
.unwrap(), .unwrap(),
GeometryLabel::Core GeometryLabel::Core
) )
}) })
.map(|node| { .map(|ni| {
self.graph self.weight(ni)
.node_weight(node) .retag(ni)
.unwrap()
.retag(node)
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
}) })
@ -390,19 +416,17 @@ impl<
pub fn inner(&self, bend: BI) -> Option<BI> { pub fn inner(&self, bend: BI) -> Option<BI> {
self.graph self.graph
.neighbors_directed(bend.node_index(), Incoming) .neighbors_directed(bend.node_index(), Incoming)
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.graph self.graph
.edge_weight(self.graph.find_edge(*node, bend.node_index()).unwrap()) .edge_weight(self.graph.find_edge(*ni, bend.node_index()).unwrap())
.unwrap(), .unwrap(),
GeometryLabel::Outer GeometryLabel::Outer
) )
}) })
.map(|node| { .map(|ni| {
self.graph self.weight(ni)
.node_weight(node) .retag(ni)
.unwrap()
.retag(node)
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
}) })
@ -412,19 +436,17 @@ impl<
pub fn outer(&self, bend: BI) -> Option<BI> { pub fn outer(&self, bend: BI) -> Option<BI> {
self.graph self.graph
.neighbors_directed(bend.node_index(), Outgoing) .neighbors_directed(bend.node_index(), Outgoing)
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.graph self.graph
.edge_weight(self.graph.find_edge(bend.node_index(), *node).unwrap()) .edge_weight(self.graph.find_edge(bend.node_index(), *ni).unwrap())
.unwrap(), .unwrap(),
GeometryLabel::Outer GeometryLabel::Outer
) )
}) })
.map(|node| { .map(|ni| {
self.graph self.weight(ni)
.node_weight(node) .retag(ni)
.unwrap()
.retag(node)
.try_into() .try_into()
.unwrap_or_else(|_| unreachable!()) .unwrap_or_else(|_| unreachable!())
}) })

View File

@ -10,7 +10,7 @@ use crate::{
geometry::{GeometryIndex, MakePrimitive}, geometry::{GeometryIndex, MakePrimitive},
seg::{LoneLooseSegIndex, SeqLooseSegIndex}, seg::{LoneLooseSegIndex, SeqLooseSegIndex},
}, },
primitive::{GetEnds, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg}, primitive::{GetJoints, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg},
}; };
#[enum_dispatch] #[enum_dispatch]
@ -80,7 +80,7 @@ impl<'a> GetNextLoose for LoneLooseSeg<'a> {
impl<'a> GetNextLoose for SeqLooseSeg<'a> { impl<'a> GetNextLoose for SeqLooseSeg<'a> {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
let ends = self.ends(); let ends = self.joints();
let Some(prev) = maybe_prev else { let Some(prev) = maybe_prev else {
return Some(ends.1.into()); return Some(ends.1.into());
}; };
@ -98,7 +98,7 @@ impl<'a> GetNextLoose for SeqLooseSeg<'a> {
impl<'a> GetNextLoose for LooseBend<'a> { impl<'a> GetNextLoose for LooseBend<'a> {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
let ends = self.ends(); let ends = self.joints();
let Some(prev) = maybe_prev else { let Some(prev) = maybe_prev else {
unreachable!(); unreachable!();
}; };

View File

@ -4,6 +4,7 @@ use petgraph::Direction::{Incoming, Outgoing};
use crate::connectivity::{BandIndex, ComponentIndex, GetNet}; use crate::connectivity::{BandIndex, ComponentIndex, GetNet};
use crate::graph::{GenericIndex, GetNodeIndex}; use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::dot::DotWeight;
use crate::layout::seg::{ use crate::layout::seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SeqLooseSegIndex, SeqLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
@ -47,8 +48,8 @@ pub trait MakeShape {
} }
#[enum_dispatch] #[enum_dispatch]
pub trait GetLegs { pub trait GetLimbs {
fn legs(&self) -> Vec<GeometryIndex> { fn limbs(&self) -> Vec<GeometryIndex> {
let mut v = vec![]; let mut v = vec![];
v.extend(self.segs().into_iter().map(Into::<GeometryIndex>::into)); v.extend(self.segs().into_iter().map(Into::<GeometryIndex>::into));
v.extend(self.bends().into_iter().map(Into::<GeometryIndex>::into)); v.extend(self.bends().into_iter().map(Into::<GeometryIndex>::into));
@ -68,9 +69,9 @@ pub trait GetInterior<T> {
fn interior(&self) -> Vec<T>; fn interior(&self) -> Vec<T>;
} }
pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T> { pub trait GetOtherJoint<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetJoints<F, T> {
fn other_end(&self, end: F) -> F { fn other_joint(&self, end: F) -> F {
let ends = self.ends(); let ends = self.joints();
if ends.0.node_index() != end.node_index() { if ends.0.node_index() != end.node_index() {
ends.0 ends.0
} else { } else {
@ -79,8 +80,8 @@ pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
} }
} }
pub trait GetEnds<F, T> { pub trait GetJoints<F, T> {
fn ends(&self) -> (F, T); fn joints(&self) -> (F, T);
} }
pub trait GetFirstRail: GetLayout + GetNodeIndex { pub trait GetFirstRail: GetLayout + GetNodeIndex {
@ -88,7 +89,7 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
self.layout() self.layout()
.geometry() .geometry()
.first_rail(self.node_index()) .first_rail(self.node_index())
.map(|node| LooseBendIndex::new(node.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
} }
} }
@ -112,14 +113,14 @@ pub trait GetInnerOuter: GetLayout + GetBendIndex {
self.layout() self.layout()
.geometry() .geometry()
.inner(self.bend_index()) .inner(self.bend_index())
.map(|node| LooseBendIndex::new(node.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
} }
fn outer(&self) -> Option<LooseBendIndex> { fn outer(&self) -> Option<LooseBendIndex> {
self.layout() self.layout()
.geometry() .geometry()
.outer(self.bend_index()) .outer(self.bend_index())
.map(|node| LooseBendIndex::new(node.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
} }
} }
@ -175,7 +176,7 @@ macro_rules! impl_loose_primitive {
}; };
} }
#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape, GetLegs)] #[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape, GetLimbs)]
pub enum Primitive<'a> { pub enum Primitive<'a> {
FixedDot(FixedDot<'a>), FixedDot(FixedDot<'a>),
LooseDot(LooseDot<'a>), LooseDot(LooseDot<'a>),
@ -206,31 +207,6 @@ impl<'a, W> GenericPrimitive<'a, W> {
.unwrap() .unwrap()
} }
fn joints(&self) -> Vec<NodeIndex<usize>> {
self.layout
.geometry()
.graph()
.neighbors_undirected(self.index.node_index())
.filter(|node| {
matches!(
self.layout
.geometry()
.graph()
.edge_weight(
self.layout
.geometry()
.graph()
.find_edge_undirected(self.index.node_index(), *node)
.unwrap()
.0,
)
.unwrap(),
GeometryLabel::Joint
)
})
.collect()
}
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> { fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> {
GenericPrimitive::new(index, &self.layout) GenericPrimitive::new(index, &self.layout)
} }
@ -270,12 +246,21 @@ impl_fixed_primitive!(FixedDot, FixedDotWeight);
impl<'a> FixedDot<'a> { impl<'a> FixedDot<'a> {
pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> { pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> {
self.joints().into_iter().find_map(|node| { self.layout
let weight = self.layout.geometry().graph().node_weight(node).unwrap(); .geometry()
.connections(self.index.into())
.into_iter()
.find_map(|ni| {
let weight = self
.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap();
if matches!(weight, GeometryWeight::LoneLooseSeg(..)) { if matches!(weight, GeometryWeight::LoneLooseSeg(..)) {
Some(LoneLooseSegIndex::new(node).into()) Some(LoneLooseSegIndex::new(ni.node_index()).into())
} else if matches!(weight, GeometryWeight::SeqLooseSeg(..)) { } else if matches!(weight, GeometryWeight::SeqLooseSeg(..)) {
Some(SeqLooseSegIndex::new(node).into()) Some(SeqLooseSegIndex::new(ni.node_index()).into())
} else { } else {
None None
} }
@ -289,37 +274,51 @@ impl<'a> MakeShape for FixedDot<'a> {
} }
} }
impl<'a> GetLegs for FixedDot<'a> { impl<'a> GetLimbs for FixedDot<'a> {
fn segs(&self) -> Vec<SegIndex> { fn segs(&self) -> Vec<SegIndex> {
self.joints() self.layout
.geometry()
.connections(self.index.into())
.into_iter() .into_iter()
.filter_map( .filter_map(|ni| {
|node| match self.layout.geometry().graph().node_weight(node).unwrap() { match self
GeometryWeight::FixedSeg(_seg) => { .layout
Some(SegIndex::Fixed(FixedSegIndex::new(node))) .geometry()
} .graph()
GeometryWeight::LoneLooseSeg(_seg) => { .node_weight(ni.node_index())
Some(SegIndex::LoneLoose(LoneLooseSegIndex::new(node).into())) .unwrap()
} {
GeometryWeight::SeqLooseSeg(_seg) => { GeometryWeight::FixedSeg(..) => {
Some(SegIndex::SeqLoose(SeqLooseSegIndex::new(node).into())) Some(SegIndex::Fixed(FixedSegIndex::new(ni.node_index())))
} }
GeometryWeight::LoneLooseSeg(..) => Some(SegIndex::LoneLoose(
LoneLooseSegIndex::new(ni.node_index()).into(),
)),
GeometryWeight::SeqLooseSeg(..) => Some(SegIndex::SeqLoose(
SeqLooseSegIndex::new(ni.node_index()).into(),
)),
_ => None, _ => None,
}, }
) })
.collect() .collect()
} }
fn bends(&self) -> Vec<BendIndex> { fn bends(&self) -> Vec<BendIndex> {
self.joints() self.layout
.geometry()
.connections(self.index.into())
.into_iter() .into_iter()
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(), self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::FixedBend(..) GeometryWeight::FixedBend(..)
) )
}) })
.map(|node| FixedBendIndex::new(node).into()) .map(|ni| FixedBendIndex::new(ni.node_index()).into())
.collect() .collect()
} }
} }
@ -331,28 +330,40 @@ impl_loose_primitive!(LooseDot, LooseDotWeight);
impl<'a> LooseDot<'a> { impl<'a> LooseDot<'a> {
pub fn seg(&self) -> Option<SeqLooseSegIndex> { pub fn seg(&self) -> Option<SeqLooseSegIndex> {
self.joints() self.layout
.geometry()
.connections(self.index.into())
.into_iter() .into_iter()
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(), self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::SeqLooseSeg(..) GeometryWeight::SeqLooseSeg(..)
) )
}) })
.map(|node| SeqLooseSegIndex::new(node)) .map(|ni| SeqLooseSegIndex::new(ni.node_index()))
.next() .next()
} }
pub fn bend(&self) -> LooseBendIndex { pub fn bend(&self) -> LooseBendIndex {
self.joints() self.layout
.geometry()
.connections(self.index.into())
.into_iter() .into_iter()
.filter(|node| { .filter(|ni| {
matches!( matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(), self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::LooseBend(..) GeometryWeight::LooseBend(..)
) )
}) })
.map(|node| LooseBendIndex::new(node)) .map(|ni| LooseBendIndex::new(ni.node_index()))
.next() .next()
.unwrap() .unwrap()
} }
@ -364,7 +375,7 @@ impl<'a> MakeShape for LooseDot<'a> {
} }
} }
impl<'a> GetLegs for LooseDot<'a> { impl<'a> GetLimbs for LooseDot<'a> {
fn segs(&self) -> Vec<SegIndex> { fn segs(&self) -> Vec<SegIndex> {
if let Some(seg) = self.seg() { if let Some(seg) = self.seg() {
vec![seg.into()] vec![seg.into()]
@ -387,16 +398,19 @@ impl<'a> MakeShape for FixedSeg<'a> {
} }
} }
impl<'a> GetLegs for FixedSeg<'a> {} impl<'a> GetLimbs for FixedSeg<'a> {}
impl<'a> GetEnds<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> { impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints(); let (from, to) = self.layout.geometry().seg_joints(self.index.into());
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) (
FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()),
)
} }
} }
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {} impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {}
pub type LoneLooseSeg<'a> = GenericPrimitive<'a, LoneLooseSegWeight>; pub type LoneLooseSeg<'a> = GenericPrimitive<'a, LoneLooseSegWeight>;
impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight); impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight);
@ -407,16 +421,19 @@ impl<'a> MakeShape for LoneLooseSeg<'a> {
} }
} }
impl<'a> GetLegs for LoneLooseSeg<'a> {} impl<'a> GetLimbs for LoneLooseSeg<'a> {}
impl<'a> GetEnds<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> { impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints(); let (from, to) = self.layout.geometry().seg_joints(self.index.into());
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) (
FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()),
)
} }
} }
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {} impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {}
pub type SeqLooseSeg<'a> = GenericPrimitive<'a, SeqLooseSegWeight>; pub type SeqLooseSeg<'a> = GenericPrimitive<'a, SeqLooseSegWeight>;
impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight); impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight);
@ -427,26 +444,31 @@ impl<'a> MakeShape for SeqLooseSeg<'a> {
} }
} }
impl<'a> GetLegs for SeqLooseSeg<'a> {} impl<'a> GetLimbs for SeqLooseSeg<'a> {}
impl<'a> GetEnds<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> { impl<'a> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {
fn ends(&self) -> (DotIndex, LooseDotIndex) { fn joints(&self) -> (DotIndex, LooseDotIndex) {
let v = self.joints(); let joints = self.layout.geometry().seg_joints(self.index.into());
if let GeometryWeight::FixedDot(..) = if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.0) {
self.layout.geometry().graph().node_weight(v[0]).unwrap() (
{ FixedDotIndex::new(joints.0.node_index()).into(),
(FixedDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1])) LooseDotIndex::new(joints.1.node_index()).into(),
} else if let GeometryWeight::FixedDot(..) = )
self.layout.geometry().graph().node_weight(v[1]).unwrap() } else if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.1) {
{ (
(FixedDotIndex::new(v[1]).into(), LooseDotIndex::new(v[0])) FixedDotIndex::new(joints.1.node_index()).into(),
LooseDotIndex::new(joints.0.node_index()),
)
} else { } else {
(LooseDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1])) (
LooseDotIndex::new(joints.0.node_index()).into(),
LooseDotIndex::new(joints.1.node_index()).into(),
)
} }
} }
} }
impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {} impl<'a> GetOtherJoint<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {}
pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>; pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>;
impl_fixed_primitive!(FixedBend, FixedBendWeight); impl_fixed_primitive!(FixedBend, FixedBendWeight);
@ -463,16 +485,19 @@ impl<'a> MakeShape for FixedBend<'a> {
} }
} }
impl<'a> GetLegs for FixedBend<'a> {} impl<'a> GetLimbs for FixedBend<'a> {}
impl<'a> GetEnds<FixedDotIndex, FixedDotIndex> for FixedBend<'a> { impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints(); let (from, to) = self.layout.geometry().bend_joints(self.index.into());
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) (
FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()),
)
} }
} }
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {} impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {}
impl<'a> GetFirstRail for FixedBend<'a> {} impl<'a> GetFirstRail for FixedBend<'a> {}
impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually. impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually.
//impl<'a> GetInnerOuter for FixedBend<'a> {} //impl<'a> GetInnerOuter for FixedBend<'a> {}
@ -498,7 +523,7 @@ impl<'a> MakeShape for LooseBend<'a> {
} }
} }
impl<'a> GetLegs for LooseBend<'a> {} impl<'a> GetLimbs for LooseBend<'a> {}
impl<'a> GetOffset for LooseBend<'a> { impl<'a> GetOffset for LooseBend<'a> {
fn offset(&self) -> f64 { fn offset(&self) -> f64 {
@ -506,13 +531,16 @@ impl<'a> GetOffset for LooseBend<'a> {
} }
} }
impl<'a> GetEnds<LooseDotIndex, LooseDotIndex> for LooseBend<'a> { impl<'a> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
fn ends(&self) -> (LooseDotIndex, LooseDotIndex) { fn joints(&self) -> (LooseDotIndex, LooseDotIndex) {
let v = self.joints(); let (from, to) = self.layout.geometry().bend_joints(self.index.into());
(LooseDotIndex::new(v[0]), LooseDotIndex::new(v[1])) (
LooseDotIndex::new(from.node_index()),
LooseDotIndex::new(to.node_index()),
)
} }
} }
impl<'a> GetOtherEnd<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {} impl<'a> GetOtherJoint<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {}
impl<'a> GetCore for LooseBend<'a> {} impl<'a> GetCore for LooseBend<'a> {}
impl<'a> GetInnerOuter for LooseBend<'a> {} impl<'a> GetInnerOuter for LooseBend<'a> {}

View File

@ -3,7 +3,7 @@ use crate::{
layout::{ layout::{
bend::LooseBendIndex, dot::LooseDotIndex, geometry::GeometryIndex, seg::SeqLooseSegIndex, bend::LooseBendIndex, dot::LooseDotIndex, geometry::GeometryIndex, seg::SeqLooseSegIndex,
}, },
primitive::{GetEnds, GetInterior, GetOtherEnd, LooseBend, LooseDot}, primitive::{GetInterior, GetJoints, GetOtherJoint, LooseBend, LooseDot},
}; };
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -16,7 +16,7 @@ pub struct Segbend {
impl Segbend { impl Segbend {
pub fn from_dot(dot: LooseDotIndex, layout: &Layout) -> Self { pub fn from_dot(dot: LooseDotIndex, layout: &Layout) -> Self {
let bend = LooseDot::new(dot, layout).bend(); let bend = LooseDot::new(dot, layout).bend();
let dot = LooseBend::new(bend, layout).other_end(dot); let dot = LooseBend::new(bend, layout).other_joint(dot);
let seg = LooseDot::new(dot, layout).seg().unwrap(); let seg = LooseDot::new(dot, layout).seg().unwrap();
Self { bend, dot, seg } Self { bend, dot, seg }
} }
@ -28,8 +28,8 @@ impl GetInterior<GeometryIndex> for Segbend {
} }
} }
impl GetEnds<SeqLooseSegIndex, LooseBendIndex> for Segbend { impl GetJoints<SeqLooseSegIndex, LooseBendIndex> for Segbend {
fn ends(&self) -> (SeqLooseSegIndex, LooseBendIndex) { fn joints(&self) -> (SeqLooseSegIndex, LooseBendIndex) {
(self.seg, self.bend) (self.seg, self.bend)
} }
} }