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},
},
loose::{GetNextLoose, LooseIndex},
primitive::{GetEnds, GetOtherEnd, MakeShape},
primitive::{GetJoints, GetOtherJoint, MakeShape},
shape::ShapeTrait,
};
@ -52,10 +52,10 @@ impl<'a> Band<'a> {
match prev {
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)) => {
if let DotIndex::Fixed(dot) = self.layout.primitive(seg).ends().0 {
if let DotIndex::Fixed(dot) = self.layout.primitive(seg).joints().0 {
Some(dot)
} else {
None

View File

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

View File

@ -10,7 +10,7 @@ use crate::{
geometry::{GetBandIndex, MakePrimitive},
},
math::{self, Circle, NoTangents},
primitive::{GetCore, GetInnerOuter, GetOtherEnd, GetWeight, MakeShape},
primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape},
rules::{Conditions, Rules},
segbend::Segbend,
shape::{Shape, ShapeTrait},
@ -230,6 +230,6 @@ impl<'a, 'b> Guide<'a, 'b> {
fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout
.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::math::NoTangents;
use crate::primitive::{
GenericPrimitive, GetConnectable, GetCore, GetEnds, GetInnerOuter, GetLegs, GetOtherEnd,
GenericPrimitive, GetConnectable, GetCore, GetInnerOuter, GetJoints, GetLimbs, GetOtherJoint,
GetWeight, MakeShape,
};
use crate::segbend::Segbend;
@ -303,7 +303,7 @@ impl Layout {
// Segs must not cross.
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());
return Err(collision.into());
}
@ -375,7 +375,7 @@ impl Layout {
let mut bow: Vec<GeometryIndex> = vec![];
bow.push(bend.into());
let ends = self.primitive(bend).ends();
let ends = self.primitive(bend).joints();
bow.push(ends.0.into());
bow.push(ends.1.into());
@ -401,7 +401,7 @@ impl Layout {
outer_bows.push(outer.into());
let ends = primitive.ends();
let ends = primitive.joints();
outer_bows.push(ends.0.into());
outer_bows.push(ends.1.into());
@ -453,7 +453,7 @@ impl Layout {
while let Some(rail) = maybe_rail {
let primitive = self.primitive(rail);
let cw = primitive.weight().cw;
let ends = primitive.ends();
let ends = primitive.joints();
let rules = Default::default();
let conditions = Default::default();
@ -843,7 +843,7 @@ impl Layout {
to: Point,
infringables: &[GeometryIndex],
) -> 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 old_weight = weight;
@ -872,11 +872,11 @@ impl Layout {
.node_weight_mut(dot.node_index())
.unwrap() = old_weight;
self.insert_into_rtree_with_legs(dot.into());
self.insert_into_rtree_with_limbs(dot.into());
return Err(infringement);
}
self.insert_into_rtree_with_legs(dot.into());
self.insert_into_rtree_with_limbs(dot.into());
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().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);
for leg in node.primitive(self).legs() {
self.insert_into_rtree(leg);
for limb in node.primitive(self).limbs() {
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().edge_count() == old(self.geometry.graph().edge_count()))]
fn remove_from_rtree_with_legs(&mut self, node: GeometryIndex) {
for leg in node.primitive(self).legs() {
self.remove_from_rtree(leg);
fn remove_from_rtree_with_limbs(&mut self, node: GeometryIndex) {
for limb in node.primitive(self).limbs() {
self.remove_from_rtree(limb);
}
self.remove_from_rtree(node);

View File

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

View File

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

View File

@ -4,6 +4,7 @@ use petgraph::Direction::{Incoming, Outgoing};
use crate::connectivity::{BandIndex, ComponentIndex, GetNet};
use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::dot::DotWeight;
use crate::layout::seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SeqLooseSegIndex, SeqLooseSegWeight,
@ -47,8 +48,8 @@ pub trait MakeShape {
}
#[enum_dispatch]
pub trait GetLegs {
fn legs(&self) -> Vec<GeometryIndex> {
pub trait GetLimbs {
fn limbs(&self) -> Vec<GeometryIndex> {
let mut v = vec![];
v.extend(self.segs().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>;
}
pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T> {
fn other_end(&self, end: F) -> F {
let ends = self.ends();
pub trait GetOtherJoint<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetJoints<F, T> {
fn other_joint(&self, end: F) -> F {
let ends = self.joints();
if ends.0.node_index() != end.node_index() {
ends.0
} else {
@ -79,8 +80,8 @@ pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
}
}
pub trait GetEnds<F, T> {
fn ends(&self) -> (F, T);
pub trait GetJoints<F, T> {
fn joints(&self) -> (F, T);
}
pub trait GetFirstRail: GetLayout + GetNodeIndex {
@ -88,7 +89,7 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
self.layout()
.geometry()
.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()
.geometry()
.inner(self.bend_index())
.map(|node| LooseBendIndex::new(node.node_index()))
.map(|ni| LooseBendIndex::new(ni.node_index()))
}
fn outer(&self) -> Option<LooseBendIndex> {
self.layout()
.geometry()
.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> {
FixedDot(FixedDot<'a>),
LooseDot(LooseDot<'a>),
@ -206,31 +207,6 @@ impl<'a, W> GenericPrimitive<'a, W> {
.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> {
GenericPrimitive::new(index, &self.layout)
}
@ -270,16 +246,25 @@ impl_fixed_primitive!(FixedDot, FixedDotWeight);
impl<'a> FixedDot<'a> {
pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> {
self.joints().into_iter().find_map(|node| {
let weight = self.layout.geometry().graph().node_weight(node).unwrap();
if matches!(weight, GeometryWeight::LoneLooseSeg(..)) {
Some(LoneLooseSegIndex::new(node).into())
} else if matches!(weight, GeometryWeight::SeqLooseSeg(..)) {
Some(SeqLooseSegIndex::new(node).into())
} else {
None
}
})
self.layout
.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(..)) {
Some(LoneLooseSegIndex::new(ni.node_index()).into())
} else if matches!(weight, GeometryWeight::SeqLooseSeg(..)) {
Some(SeqLooseSegIndex::new(ni.node_index()).into())
} else {
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> {
self.joints()
self.layout
.geometry()
.connections(self.index.into())
.into_iter()
.filter_map(
|node| match self.layout.geometry().graph().node_weight(node).unwrap() {
GeometryWeight::FixedSeg(_seg) => {
Some(SegIndex::Fixed(FixedSegIndex::new(node)))
}
GeometryWeight::LoneLooseSeg(_seg) => {
Some(SegIndex::LoneLoose(LoneLooseSegIndex::new(node).into()))
}
GeometryWeight::SeqLooseSeg(_seg) => {
Some(SegIndex::SeqLoose(SeqLooseSegIndex::new(node).into()))
.filter_map(|ni| {
match self
.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap()
{
GeometryWeight::FixedSeg(..) => {
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,
},
)
}
})
.collect()
}
fn bends(&self) -> Vec<BendIndex> {
self.joints()
self.layout
.geometry()
.connections(self.index.into())
.into_iter()
.filter(|node| {
.filter(|ni| {
matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(),
self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::FixedBend(..)
)
})
.map(|node| FixedBendIndex::new(node).into())
.map(|ni| FixedBendIndex::new(ni.node_index()).into())
.collect()
}
}
@ -331,28 +330,40 @@ impl_loose_primitive!(LooseDot, LooseDotWeight);
impl<'a> LooseDot<'a> {
pub fn seg(&self) -> Option<SeqLooseSegIndex> {
self.joints()
self.layout
.geometry()
.connections(self.index.into())
.into_iter()
.filter(|node| {
.filter(|ni| {
matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(),
self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::SeqLooseSeg(..)
)
})
.map(|node| SeqLooseSegIndex::new(node))
.map(|ni| SeqLooseSegIndex::new(ni.node_index()))
.next()
}
pub fn bend(&self) -> LooseBendIndex {
self.joints()
self.layout
.geometry()
.connections(self.index.into())
.into_iter()
.filter(|node| {
.filter(|ni| {
matches!(
self.layout.geometry().graph().node_weight(*node).unwrap(),
self.layout
.geometry()
.graph()
.node_weight(ni.node_index())
.unwrap(),
GeometryWeight::LooseBend(..)
)
})
.map(|node| LooseBendIndex::new(node))
.map(|ni| LooseBendIndex::new(ni.node_index()))
.next()
.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> {
if let Some(seg) = self.seg() {
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> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints();
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1]))
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into());
(
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>;
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> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints();
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1]))
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into());
(
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>;
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> {
fn ends(&self) -> (DotIndex, LooseDotIndex) {
let v = self.joints();
if let GeometryWeight::FixedDot(..) =
self.layout.geometry().graph().node_weight(v[0]).unwrap()
{
(FixedDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1]))
} else if let GeometryWeight::FixedDot(..) =
self.layout.geometry().graph().node_weight(v[1]).unwrap()
{
(FixedDotIndex::new(v[1]).into(), LooseDotIndex::new(v[0]))
impl<'a> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {
fn joints(&self) -> (DotIndex, LooseDotIndex) {
let joints = self.layout.geometry().seg_joints(self.index.into());
if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.0) {
(
FixedDotIndex::new(joints.0.node_index()).into(),
LooseDotIndex::new(joints.1.node_index()).into(),
)
} else if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.1) {
(
FixedDotIndex::new(joints.1.node_index()).into(),
LooseDotIndex::new(joints.0.node_index()),
)
} 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>;
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> {
fn ends(&self) -> (FixedDotIndex, FixedDotIndex) {
let v = self.joints();
(FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1]))
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into());
(
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> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually.
//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> {
fn offset(&self) -> f64 {
@ -506,13 +531,16 @@ impl<'a> GetOffset for LooseBend<'a> {
}
}
impl<'a> GetEnds<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
fn ends(&self) -> (LooseDotIndex, LooseDotIndex) {
let v = self.joints();
(LooseDotIndex::new(v[0]), LooseDotIndex::new(v[1]))
impl<'a> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
fn joints(&self) -> (LooseDotIndex, LooseDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into());
(
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> GetInnerOuter for LooseBend<'a> {}

View File

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