From c855853a799d209b6c917e0fbb5a7e4a8ee719f2 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sun, 28 Jan 2024 00:35:16 +0000 Subject: [PATCH] primitive,geometry: move dot, seg shape-making code to `Geometry` We still need to move the code for bends -- but that's for tomorrow. --- src/draw.rs | 24 +++++++++-- src/graph.rs | 23 ++++++----- src/layout.rs | 2 +- src/layout/bend.rs | 9 ++++- src/layout/dot.rs | 19 +++++++-- src/layout/geometry.rs | 92 +++++++++++++++++++++++++++++++++--------- src/layout/seg.rs | 16 +++++++- src/primitive.rs | 76 +++++++++------------------------- 8 files changed, 164 insertions(+), 97 deletions(-) diff --git a/src/draw.rs b/src/draw.rs index 13f3b29..8a66cc6 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -62,12 +62,26 @@ impl<'a> Draw<'a> { match head.face() { DotIndex::Fixed(dot) => { self.layout - .add_lone_loose_seg(dot, into.into(), LoneLooseSegWeight { band: head.band() }) + .add_lone_loose_seg( + dot, + into.into(), + LoneLooseSegWeight { + band: head.band(), + width: 3.0, + }, + ) .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; } DotIndex::Loose(dot) => { self.layout - .add_seq_loose_seg(into.into(), dot, SeqLooseSegWeight { band: head.band() }) + .add_seq_loose_seg( + into.into(), + dot, + SeqLooseSegWeight { + band: head.band(), + width: 3.0, + }, + ) .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; } } @@ -205,9 +219,13 @@ impl<'a> Draw<'a> { r: width / 2.0, }, }, - SeqLooseSegWeight { band: head.band() }, + SeqLooseSegWeight { + band: head.band(), + width: 3.0, + }, LooseBendWeight { band: head.band(), + width: 3.0, offset: 3.0, cw, }, diff --git a/src/graph.rs b/src/graph.rs index 9fb264f..0cfe713 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -8,7 +8,10 @@ use petgraph::stable_graph::NodeIndex; // Due to apparent limitations of enum_dispatch we're forced to import some types backwards. -use crate::layout::{bend::BendIndex, dot::DotIndex, geometry::GeometryIndex, seg::SegIndex}; +#[enum_dispatch] +pub trait NewFromNodeIndex { + fn new(index: NodeIndex) -> Self; +} #[enum_dispatch] pub trait GetNodeIndex { @@ -21,15 +24,6 @@ pub struct GenericIndex { marker: PhantomData, } -impl GenericIndex { - pub fn new(index: NodeIndex) -> Self { - Self { - node_index: index, - marker: PhantomData, - } - } -} - impl Hash for GenericIndex { fn hash(&self, state: &mut H) { self.node_index.hash(state) @@ -44,6 +38,15 @@ impl PartialEq for GenericIndex { impl Eq for GenericIndex {} +impl NewFromNodeIndex for GenericIndex { + fn new(index: NodeIndex) -> Self { + Self { + node_index: index, + marker: PhantomData, + } + } +} + impl GetNodeIndex for GenericIndex { fn node_index(&self) -> NodeIndex { self.node_index diff --git a/src/layout.rs b/src/layout.rs index 7755a9b..2bb87c3 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -19,7 +19,7 @@ use crate::connectivity::{ BandIndex, BandWeight, ComponentIndex, ComponentWeight, ConnectivityGraph, ConnectivityLabel, ConnectivityWeight, GetNet, }; -use crate::graph::{GenericIndex, GetNodeIndex}; +use crate::graph::{GenericIndex, GetNodeIndex, NewFromNodeIndex}; use crate::guide::Guide; use crate::layout::bend::BendIndex; use crate::layout::dot::DotWeight; diff --git a/src/layout/bend.rs b/src/layout/bend.rs index 27ae154..34cdbc5 100644 --- a/src/layout/bend.rs +++ b/src/layout/bend.rs @@ -3,7 +3,7 @@ use enum_dispatch::enum_dispatch; use crate::{ connectivity::{BandIndex, ComponentIndex}, graph::GenericIndex, - layout::{GetNodeIndex, Layout}, + layout::{GetNodeIndex, Layout, NewFromNodeIndex}, primitive::{GenericPrimitive, Primitive}, }; @@ -48,10 +48,17 @@ impl GetWidth for FixedBendWeight { #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseBendWeight { pub band: BandIndex, + pub width: f64, pub offset: f64, pub cw: bool, } +impl GetWidth for LooseBendWeight { + fn width(&self) -> f64 { + self.width + } +} + impl GetOffset for LooseBendWeight { fn offset(&self) -> f64 { self.offset diff --git a/src/layout/dot.rs b/src/layout/dot.rs index 062fd39..b6c2a0f 100644 --- a/src/layout/dot.rs +++ b/src/layout/dot.rs @@ -1,16 +1,17 @@ use enum_dispatch::enum_dispatch; +use geo::Point; use crate::{ connectivity::{BandIndex, ComponentIndex}, graph::GenericIndex, - layout::{GetNodeIndex, Layout}, + layout::{GetNodeIndex, Layout, NewFromNodeIndex}, math::Circle, primitive::{GenericPrimitive, Primitive}, }; use super::geometry::{ DotWeightTrait, GeometryIndex, GeometryWeight, GetBandIndex, GetComponentIndex, - GetComponentIndexMut, GetWidth, MakePrimitive, Retag, + GetComponentIndexMut, GetPos, GetWidth, MakePrimitive, Retag, }; use petgraph::stable_graph::NodeIndex; @@ -30,7 +31,7 @@ impl From for GeometryIndex { } } -#[enum_dispatch(GetWidth)] +#[enum_dispatch(GetPos, GetWidth)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum DotWeight { Fixed(FixedDotWeight), @@ -69,6 +70,12 @@ pub struct FixedDotWeight { impl_fixed_weight!(FixedDotWeight, FixedDot, FixedDotIndex); impl DotWeightTrait for FixedDotWeight {} +impl GetPos for FixedDotWeight { + fn pos(&self) -> Point { + self.circle.pos + } +} + impl GetWidth for FixedDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 @@ -84,6 +91,12 @@ pub struct LooseDotWeight { impl_loose_weight!(LooseDotWeight, LooseDot, LooseDotIndex); impl DotWeightTrait for LooseDotWeight {} +impl GetPos for LooseDotWeight { + fn pos(&self) -> Point { + self.circle.pos + } +} + impl GetWidth for LooseDotWeight { fn width(&self) -> f64 { self.circle.r * 2.0 diff --git a/src/layout/geometry.rs b/src/layout/geometry.rs index bb3d435..bdde36e 100644 --- a/src/layout/geometry.rs +++ b/src/layout/geometry.rs @@ -7,9 +7,11 @@ use petgraph::stable_graph::{NodeIndex, StableDiGraph}; use crate::{ connectivity::{BandIndex, ComponentIndex}, - graph::{GenericIndex, GetNodeIndex}, + graph::{GenericIndex, GetNodeIndex, NewFromNodeIndex}, layout::Layout, + math::Circle, primitive::Primitive, + shape::{DotShape, SegShape, Shape}, }; use super::{ @@ -39,6 +41,11 @@ pub trait GetBandIndex { fn band(&self) -> BandIndex; } +#[enum_dispatch] +pub trait GetPos { + fn pos(&self) -> Point; +} + #[enum_dispatch] pub trait GetWidth { fn width(&self) -> f64; @@ -97,7 +104,7 @@ macro_rules! impl_loose_weight { }; } -#[enum_dispatch(Retag)] +#[enum_dispatch(GetWidth, Retag)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum GeometryWeight { FixedDot(FixedDotWeight), @@ -123,7 +130,7 @@ pub enum GeometryIndex { #[derive(Debug, Clone, Copy, PartialEq)] pub enum GeometryLabel { - Adjacent, + Joint, Outer, Core, } @@ -133,13 +140,13 @@ pub trait MakePrimitive { fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>; } -pub trait DotWeightTrait: GetWidth + Into + Copy {} -pub trait SegWeightTrait: Into + Copy {} -pub trait BendWeightTrait: Into + Copy {} +pub trait DotWeightTrait: GetPos + GetWidth + Into + Copy {} +pub trait SegWeightTrait: GetWidth + Into + Copy {} +pub trait BendWeightTrait: GetWidth + Into + Copy {} #[derive(Debug)] pub struct Geometry< - GW: TryInto, + GW: GetWidth + TryInto + Copy, DW: DotWeightTrait, DI: GetNodeIndex, SI: GetNodeIndex, @@ -154,11 +161,11 @@ pub struct Geometry< } impl< - GW: TryInto, - DW: DotWeightTrait + Copy, - DI: GetNodeIndex, - SI: GetNodeIndex, - BI: GetNodeIndex, + GW: GetWidth + TryInto + Copy, + DW: DotWeightTrait, + DI: GetNodeIndex + Copy, + SI: GetNodeIndex + Copy, + BI: GetNodeIndex + Copy, > Geometry { pub fn new() -> Self { @@ -185,9 +192,9 @@ impl< let seg = GenericIndex::::new(self.graph.add_node(weight.into())); self.graph - .update_edge(from.node_index(), seg.node_index(), GeometryLabel::Adjacent); + .update_edge(from.node_index(), seg.node_index(), GeometryLabel::Joint); self.graph - .update_edge(seg.node_index(), to.node_index(), GeometryLabel::Adjacent); + .update_edge(seg.node_index(), to.node_index(), GeometryLabel::Joint); seg } @@ -201,19 +208,64 @@ impl< ) -> GenericIndex { let bend = GenericIndex::::new(self.graph.add_node(weight.into())); - self.graph.update_edge( - from.node_index(), - bend.node_index(), - GeometryLabel::Adjacent, - ); self.graph - .update_edge(bend.node_index(), to.node_index(), GeometryLabel::Adjacent); + .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(bend.node_index(), core.node_index(), GeometryLabel::Core); bend } + pub fn dot_shape(&self, dot: DI) -> Shape { + let weight = self.dot_weight(dot); + Shape::Dot(DotShape { + c: Circle { + pos: weight.pos(), + r: weight.width() / 2.0, + }, + }) + } + + pub fn seg_shape(&self, seg: SI) -> Shape { + let joint_weights = self.joint_weights(seg.node_index()); + Shape::Seg(SegShape { + from: joint_weights[0].pos(), + to: joint_weights[1].pos(), + width: self.weight(seg.node_index()).width(), + }) + } + + fn weight(&self, index: NodeIndex) -> GW { + *self.graph.node_weight(index).unwrap() + } + + fn dot_weight(&self, dot: DI) -> DW { + self.weight(dot.node_index()) + .try_into() + .unwrap_or_else(|_| unreachable!()) + } + + fn joint_weights(&self, index: NodeIndex) -> Vec { + 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() + } + pub fn graph(&self) -> &StableDiGraph { &self.graph } diff --git a/src/layout/seg.rs b/src/layout/seg.rs index 8b371b0..9f649db 100644 --- a/src/layout/seg.rs +++ b/src/layout/seg.rs @@ -3,7 +3,7 @@ use enum_dispatch::enum_dispatch; use crate::{ connectivity::{BandIndex, ComponentIndex}, graph::GenericIndex, - layout::{GetNodeIndex, Layout}, + layout::{GetNodeIndex, Layout, NewFromNodeIndex}, primitive::{GenericPrimitive, Primitive}, }; @@ -49,15 +49,29 @@ impl GetWidth for FixedSegWeight { #[derive(Debug, Clone, Copy, PartialEq)] pub struct LoneLooseSegWeight { pub band: BandIndex, + pub width: f64, } impl_loose_weight!(LoneLooseSegWeight, LoneLooseSeg, LoneLooseSegIndex); impl SegWeightTrait for LoneLooseSegWeight {} +impl GetWidth for LoneLooseSegWeight { + fn width(&self) -> f64 { + self.width + } +} + #[derive(Debug, Clone, Copy, PartialEq)] pub struct SeqLooseSegWeight { pub band: BandIndex, + pub width: f64, } impl_loose_weight!(SeqLooseSegWeight, SeqLooseSeg, SeqLooseSegIndex); impl SegWeightTrait for SeqLooseSegWeight {} + +impl GetWidth for SeqLooseSegWeight { + fn width(&self) -> f64 { + self.width + } +} diff --git a/src/primitive.rs b/src/primitive.rs index c7499d3..1857052 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -5,7 +5,7 @@ use petgraph::stable_graph::NodeIndex; use petgraph::Direction::{Incoming, Outgoing}; use crate::connectivity::{BandIndex, ComponentIndex, GetNet}; -use crate::graph::{GenericIndex, GetNodeIndex}; +use crate::graph::{GenericIndex, GetNodeIndex, NewFromNodeIndex}; use crate::layout::seg::{ FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex, SeqLooseSegWeight, @@ -275,7 +275,7 @@ impl<'a, W> GenericPrimitive<'a, W> { .unwrap() } - fn adjacents(&self) -> Vec> { + fn joints(&self) -> Vec> { self.layout .geometry() .graph() @@ -294,7 +294,7 @@ impl<'a, W> GenericPrimitive<'a, W> { .0, ) .unwrap(), - GeometryLabel::Adjacent + GeometryLabel::Joint ) }) .collect() @@ -339,7 +339,7 @@ impl_fixed_primitive!(FixedDot, FixedDotWeight); impl<'a> FixedDot<'a> { pub fn first_loose(&self, _band: BandIndex) -> Option { - self.adjacents().into_iter().find_map(|node| { + 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()) @@ -354,15 +354,13 @@ impl<'a> FixedDot<'a> { impl<'a> MakeShape for FixedDot<'a> { fn shape(&self) -> Shape { - Shape::Dot(DotShape { - c: self.weight().circle, - }) + self.layout.geometry().dot_shape(self.index.into()) } } impl<'a> GetLegs for FixedDot<'a> { fn segs(&self) -> Vec { - self.adjacents() + self.joints() .into_iter() .filter_map( |node| match self.layout.geometry().graph().node_weight(node).unwrap() { @@ -382,7 +380,7 @@ impl<'a> GetLegs for FixedDot<'a> { } fn bends(&self) -> Vec { - self.adjacents() + self.joints() .into_iter() .filter(|node| { matches!( @@ -402,7 +400,7 @@ impl_loose_primitive!(LooseDot, LooseDotWeight); impl<'a> LooseDot<'a> { pub fn seg(&self) -> Option { - self.adjacents() + self.joints() .into_iter() .filter(|node| { matches!( @@ -415,7 +413,7 @@ impl<'a> LooseDot<'a> { } pub fn bend(&self) -> LooseBendIndex { - self.adjacents() + self.joints() .into_iter() .filter(|node| { matches!( @@ -431,9 +429,7 @@ impl<'a> LooseDot<'a> { impl<'a> MakeShape for LooseDot<'a> { fn shape(&self) -> Shape { - Shape::Dot(DotShape { - c: self.weight().circle, - }) + self.layout.geometry().dot_shape(self.index.into()) } } @@ -456,12 +452,7 @@ impl_fixed_primitive!(FixedSeg, FixedSegWeight); impl<'a> MakeShape for FixedSeg<'a> { fn shape(&self) -> Shape { - let ends = self.ends(); - Shape::Seg(SegShape { - from: self.primitive(ends.0).weight().circle.pos, - to: self.primitive(ends.1).weight().circle.pos, - width: self.width(), - }) + self.layout.geometry().seg_shape(self.index.into()) } } @@ -469,7 +460,7 @@ impl<'a> GetLegs for FixedSeg<'a> {} impl<'a> GetEnds for FixedSeg<'a> { fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { - let v = self.adjacents(); + let v = self.joints(); (FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) } } @@ -481,26 +472,15 @@ impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight); impl<'a> MakeShape for LoneLooseSeg<'a> { fn shape(&self) -> Shape { - let ends = self.ends(); - Shape::Seg(SegShape { - from: self.primitive(ends.0).weight().circle.pos, - to: self.primitive(ends.1).weight().circle.pos, - width: self.width(), - }) + self.layout.geometry().seg_shape(self.index.into()) } } impl<'a> GetLegs for LoneLooseSeg<'a> {} -impl<'a> GetWidth for LoneLooseSeg<'a> { - fn width(&self) -> f64 { - self.primitive(self.ends().1).weight().width() - } -} - impl<'a> GetEnds for LoneLooseSeg<'a> { fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { - let v = self.adjacents(); + let v = self.joints(); (FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) } } @@ -512,29 +492,15 @@ impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight); impl<'a> MakeShape for SeqLooseSeg<'a> { fn shape(&self) -> Shape { - let ends = self.ends(); - Shape::Seg(SegShape { - from: match ends.0 { - DotIndex::Fixed(dot) => self.primitive(dot).weight().circle.pos, - DotIndex::Loose(dot) => self.primitive(dot).weight().circle.pos, - }, - to: self.primitive(ends.1).weight().circle.pos, - width: self.width(), - }) + self.layout.geometry().seg_shape(self.index.into()) } } impl<'a> GetLegs for SeqLooseSeg<'a> {} -impl<'a> GetWidth for SeqLooseSeg<'a> { - fn width(&self) -> f64 { - self.primitive(self.ends().1).weight().width() - } -} - impl<'a> GetEnds for SeqLooseSeg<'a> { fn ends(&self) -> (DotIndex, LooseDotIndex) { - let v = self.adjacents(); + let v = self.joints(); if let GeometryWeight::FixedDot(..) = self.layout.geometry().graph().node_weight(v[0]).unwrap() { @@ -593,7 +559,7 @@ impl<'a> GetLegs for FixedBend<'a> {} impl<'a> GetEnds for FixedBend<'a> { fn ends(&self) -> (FixedDotIndex, FixedDotIndex) { - let v = self.adjacents(); + let v = self.joints(); (FixedDotIndex::new(v[0]), FixedDotIndex::new(v[1])) } } @@ -652,12 +618,6 @@ impl<'a> MakeShape for LooseBend<'a> { impl<'a> GetLegs for LooseBend<'a> {} -impl<'a> GetWidth for LooseBend<'a> { - fn width(&self) -> f64 { - self.primitive(self.ends().1).weight().width() - } -} - impl<'a> GetOffset for LooseBend<'a> { fn offset(&self) -> f64 { self.weight().offset @@ -666,7 +626,7 @@ impl<'a> GetOffset for LooseBend<'a> { impl<'a> GetEnds for LooseBend<'a> { fn ends(&self) -> (LooseDotIndex, LooseDotIndex) { - let v = self.adjacents(); + let v = self.joints(); (LooseDotIndex::new(v[0]), LooseDotIndex::new(v[1])) } }