From 294e6c4f7250432c8b1a1831369a89bc1bec3009 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Fri, 15 Dec 2023 01:42:09 +0000 Subject: [PATCH] graph,layout,primitive: store band index instead of net in loose weights --- Cargo.toml | 3 + src/draw.rs | 60 ++++++++++---- src/graph.rs | 63 ++++++++++----- src/guide.rs | 6 +- src/layout.rs | 38 +++++---- src/main.rs | 4 +- src/mesh.rs | 2 +- src/primitive.rs | 199 +++++++++++++++++++++++++++++++---------------- src/router.rs | 2 +- src/segbend.rs | 9 ++- src/tracer.rs | 12 ++- src/traverser.rs | 12 ++- 12 files changed, 265 insertions(+), 145 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1486f3f..3ee4bbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,9 @@ version = "0.11.0" [dependencies.petgraph] version = "0.6.3" +[dependencies.slab] +version = "0.4.9" + [dependencies.spade] version = "2.2.0" diff --git a/src/draw.rs b/src/draw.rs index 3a4ec0e..e991042 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -4,11 +4,12 @@ use geo::{EuclideanLength, Point}; use crate::{ graph::{ - BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetEnds, GetNet, Index, LooseBendIndex, - LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive, + BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetBand, GetEnds, GetNet, Index, + LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, + MakePrimitive, }, guide::Guide, - layout::Layout, + layout::{Band, Layout}, math::Circle, primitive::{GetOtherEnd, GetWeight}, rules::{Conditions, Rules}, @@ -18,6 +19,7 @@ use crate::{ #[enum_dispatch] pub trait HeadTrait { fn dot(&self) -> DotIndex; + fn band(&self) -> usize; } #[enum_dispatch(HeadTrait)] @@ -30,24 +32,34 @@ pub enum Head { #[derive(Debug, Clone, Copy)] pub struct BareHead { pub dot: FixedDotIndex, + pub band: usize, } impl HeadTrait for BareHead { fn dot(&self) -> DotIndex { self.dot.into() } + + fn band(&self) -> usize { + self.band + } } #[derive(Debug, Clone, Copy)] pub struct SegbendHead { pub dot: LooseDotIndex, pub segbend: Segbend, + pub band: usize, } impl HeadTrait for SegbendHead { fn dot(&self) -> DotIndex { self.dot.into() } + + fn band(&self) -> usize { + self.band + } } pub struct Draw<'a> { @@ -72,7 +84,7 @@ impl<'a> Draw<'a> { .head_into_dot_segment(&head, into, width)?; let head = self.extend_head(head, tangent.start_point())?; - let net = head.dot().primitive(&self.layout.graph).net(); + let net = head.dot().primitive(self.layout).net(); match head.dot() { DotIndex::Fixed(dot) => { @@ -80,8 +92,11 @@ impl<'a> Draw<'a> { .add_fixed_seg(into.into(), dot, FixedSegWeight { net, width })?; } DotIndex::Loose(dot) => { - self.layout - .add_loose_seg(into.into(), dot, LooseSegWeight { net })?; + self.layout.add_loose_seg( + into.into(), + dot, + LooseSegWeight { band: head.band() }, + )?; } } Ok(()) @@ -111,9 +126,12 @@ impl<'a> Draw<'a> { let head = self.extend_head(head, tangent.start_point())?; let _to_head = self.extend_head(to_head.into(), tangent.end_point())?; - let net = head.dot().primitive(&self.layout.graph).net(); - self.layout - .add_loose_seg(head.dot(), into.into(), LooseSegWeight { net })?; + let net = head.dot().primitive(self.layout).net(); + self.layout.add_loose_seg( + head.dot(), + into.into(), + LooseSegWeight { band: head.band() }, + )?; Ok(()) } @@ -224,23 +242,26 @@ impl<'a> Draw<'a> { cw: bool, width: f64, ) -> Result { - let net = head.dot().primitive(&self.layout.graph).net(); let segbend = self.layout.add_segbend( head.dot(), around, LooseDotWeight { - net, + band: head.band(), circle: Circle { pos: to, r: width / 2.0, }, }, - LooseSegWeight { net }, - LooseBendWeight { net, cw }, + LooseSegWeight { band: head.band() }, + LooseBendWeight { + band: head.band(), + cw, + }, )?; Ok(SegbendHead { dot: self.layout.primitive(segbend.bend).other_end(segbend.dot), segbend, + band: head.band(), }) } @@ -251,11 +272,12 @@ impl<'a> Draw<'a> { .layout .primitive(head.segbend.seg) .other_end(head.segbend.dot.into()); + let band = head.band; self.layout.remove_interior(&head.segbend); self.layout.remove(head.dot().into()); - Some(self.head(prev_dot)) + Some(self.head(prev_dot, band)) } #[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))] @@ -274,9 +296,9 @@ impl<'a> Draw<'a> { self.layout.reposition_bend(bend, from, to);*/ } - fn head(&self, dot: DotIndex) -> Head { + fn head(&self, dot: DotIndex, band: usize) -> Head { match dot { - DotIndex::Fixed(loose) => BareHead { dot: loose }.into(), + DotIndex::Fixed(loose) => BareHead { dot: loose, band }.into(), DotIndex::Loose(fixed) => self.segbend_head(fixed).into(), } } @@ -285,11 +307,15 @@ impl<'a> Draw<'a> { SegbendHead { dot, segbend: self.layout.segbend(dot), + band: self.layout.primitive(dot).weight().band(), } } fn rear_head(&self, dot: LooseDotIndex) -> Head { - self.head(self.rear(self.segbend_head(dot))) + self.head( + self.rear(self.segbend_head(dot)), + self.layout.primitive(dot).weight().band(), + ) } fn rear(&self, head: SegbendHead) -> DotIndex { diff --git a/src/graph.rs b/src/graph.rs index b77e70a..5e527f7 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -6,6 +6,7 @@ use std::{ }; use crate::{ + layout::Layout, math::Circle, primitive::{GenericPrimitive, Primitive}, }; @@ -33,6 +34,11 @@ pub trait GetNetMut { fn net_mut(&mut self) -> &mut i64; } +#[enum_dispatch] +pub trait GetBand { + fn band(&self) -> usize; +} + #[enum_dispatch] pub trait GetWidth { fn width(&self) -> f64; @@ -49,6 +55,20 @@ macro_rules! impl_weight { } } + pub type $index_struct = GenericIndex<$weight_struct>; + + impl MakePrimitive for $index_struct { + fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a> { + Primitive::$weight_variant(GenericPrimitive::new(*self, layout)) + } + } + }; +} + +macro_rules! impl_fixed_weight { + ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { + impl_weight!($weight_struct, $weight_variant, $index_struct); + impl GetNet for $weight_struct { fn net(&self) -> i64 { self.net @@ -60,21 +80,22 @@ macro_rules! impl_weight { &mut self.net } } + }; +} - pub type $index_struct = GenericIndex<$weight_struct>; +macro_rules! impl_loose_weight { + ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { + impl_weight!($weight_struct, $weight_variant, $index_struct); - impl MakePrimitive for $index_struct { - fn primitive<'a>( - &self, - graph: &'a StableDiGraph, - ) -> Primitive<'a> { - Primitive::$weight_variant(GenericPrimitive::new(*self, graph)) + impl GetBand for $weight_struct { + fn band(&self) -> usize { + self.band } } }; } -#[enum_dispatch(Retag, GetNet, GetNetMut)] +#[enum_dispatch(Retag)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum Weight { FixedDot(FixedDotWeight), @@ -144,7 +165,7 @@ impl From for Index { } } -pub trait DotWeight: GetNet + GetWidth + Into + Copy {} +pub trait DotWeight: GetWidth + Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedDotWeight { @@ -152,7 +173,7 @@ pub struct FixedDotWeight { pub circle: Circle, } -impl_weight!(FixedDotWeight, FixedDot, FixedDotIndex); +impl_fixed_weight!(FixedDotWeight, FixedDot, FixedDotIndex); impl DotWeight for FixedDotWeight {} impl GetWidth for FixedDotWeight { @@ -163,11 +184,11 @@ impl GetWidth for FixedDotWeight { #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseDotWeight { - pub net: i64, + pub band: usize, pub circle: Circle, } -impl_weight!(LooseDotWeight, LooseDot, LooseDotIndex); +impl_loose_weight!(LooseDotWeight, LooseDot, LooseDotIndex); impl DotWeight for LooseDotWeight {} impl GetWidth for LooseDotWeight { @@ -176,7 +197,7 @@ impl GetWidth for LooseDotWeight { } } -pub trait SegWeight: GetNet + Into + Copy {} +pub trait SegWeight: Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedSegWeight { @@ -184,7 +205,7 @@ pub struct FixedSegWeight { pub width: f64, } -impl_weight!(FixedSegWeight, FixedSeg, FixedSegIndex); +impl_fixed_weight!(FixedSegWeight, FixedSeg, FixedSegIndex); impl SegWeight for FixedSegWeight {} impl GetWidth for FixedSegWeight { @@ -195,13 +216,13 @@ impl GetWidth for FixedSegWeight { #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseSegWeight { - pub net: i64, + pub band: usize, } -impl_weight!(LooseSegWeight, LooseSeg, LooseSegIndex); +impl_loose_weight!(LooseSegWeight, LooseSeg, LooseSegIndex); impl SegWeight for LooseSegWeight {} -pub trait BendWeight: GetNet + Into + Copy {} +pub trait BendWeight: Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] pub struct FixedBendWeight { @@ -210,7 +231,7 @@ pub struct FixedBendWeight { pub cw: bool, } -impl_weight!(FixedBendWeight, FixedBend, FixedBendIndex); +impl_fixed_weight!(FixedBendWeight, FixedBend, FixedBendIndex); impl BendWeight for FixedBendWeight {} impl GetWidth for FixedBendWeight { @@ -221,11 +242,11 @@ impl GetWidth for FixedBendWeight { #[derive(Debug, Clone, Copy, PartialEq)] pub struct LooseBendWeight { - pub net: i64, + pub band: usize, pub cw: bool, } -impl_weight!(LooseBendWeight, LooseBend, LooseBendIndex); +impl_loose_weight!(LooseBendWeight, LooseBend, LooseBendIndex); impl BendWeight for LooseBendWeight {} #[derive(Debug, Clone, Copy, PartialEq)] @@ -242,7 +263,7 @@ pub trait GetNodeIndex { #[enum_dispatch] pub trait MakePrimitive { - fn primitive<'a>(&self, graph: &'a StableDiGraph) -> Primitive<'a>; + fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>; } #[derive(Debug, Clone, Copy)] diff --git a/src/guide.rs b/src/guide.rs index 1c4a021..9d02588 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -117,7 +117,7 @@ impl<'a, 'b> Guide<'a, 'b> { match *head { Head::Bare(head) => Circle { - pos: head.dot().primitive(&self.layout.graph).shape().center(), // TODO. + pos: head.dot().primitive(self.layout).shape().center(), // TODO. r: 0.0, }, Head::Segbend(head) => { @@ -134,7 +134,7 @@ impl<'a, 'b> Guide<'a, 'b> { } fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { - let shape = bend.primitive(&self.layout.graph).shape(); + let shape = bend.primitive(self.layout).shape(); Circle { pos: shape.center(), r: shape.width() / 2.0 @@ -145,7 +145,7 @@ impl<'a, 'b> Guide<'a, 'b> { } fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { - let shape = dot.primitive(&self.layout.graph).shape(); + let shape = dot.primitive(self.layout).shape(); Circle { pos: shape.center(), r: shape.width() / 2.0 + width + self.rules.ruleset(self.conditions).clearance.min, diff --git a/src/layout.rs b/src/layout.rs index 2002ffe..1b075aa 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -5,6 +5,7 @@ use petgraph::visit::EdgeRef; use petgraph::Direction::Incoming; use rstar::primitives::GeomWithData; use rstar::{RTree, RTreeObject}; +use slab::Slab; use crate::graph::{ BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex, @@ -18,8 +19,16 @@ use crate::shape::{Shape, ShapeTrait}; pub type RTreeWrapper = GeomWithData; +#[derive(Debug)] +pub struct Band { + pub net: i64, + pub width: f64, +} + +#[derive(Debug)] pub struct Layout { rtree: RTree, + pub bands: Slab, pub graph: StableDiGraph, } @@ -29,6 +38,7 @@ impl Layout { pub fn new() -> Self { Layout { rtree: RTree::new(), + bands: Slab::new(), graph: StableDiGraph::default(), } } @@ -178,17 +188,6 @@ impl Layout { self.insert_into_rtree(seg.into()); self.fail_and_remove_if_collides_except(seg.into(), &[])?; - *self - .graph - .node_weight_mut(from.node_index()) - .unwrap() - .net_mut() = weight.net(); - *self - .graph - .node_weight_mut(to.node_index()) - .unwrap() - .net_mut() = weight.net(); - Ok(seg) } @@ -341,7 +340,7 @@ impl Layout { }*/ pub fn segbend(&self, dot: LooseDotIndex) -> Segbend { - Segbend::from_dot(dot, &self.graph) + Segbend::from_dot(dot, self) } #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] @@ -369,8 +368,7 @@ impl Layout { } pub fn shapes(&self) -> impl Iterator + '_ { - self.node_indices() - .map(|ni| ni.primitive(&self.graph).shape()) + self.node_indices().map(|ni| ni.primitive(self).shape()) } pub fn node_count(&self) -> usize { @@ -421,17 +419,17 @@ impl Layout { } pub fn primitive(&self, index: GenericIndex) -> GenericPrimitive { - GenericPrimitive::new(index, &self.graph) + GenericPrimitive::new(index, self) } fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option { - let shape = index.primitive(&self.graph).shape(); + let shape = index.primitive(self).shape(); self.rtree .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .filter(|wrapper| { let other_index = wrapper.data; - !index.primitive(&self.graph).connectable(other_index) + !index.primitive(self).connectable(other_index) }) .filter(|wrapper| !except.contains(&wrapper.data)) .filter(|wrapper| shape.intersects(wrapper.geom())) @@ -442,14 +440,14 @@ impl Layout { #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] fn insert_into_rtree(&mut self, index: Index) { - let shape = index.primitive(&self.graph).shape(); + let shape = index.primitive(self).shape(); self.rtree.insert(RTreeWrapper::new(shape, index)); } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] fn remove_from_rtree(&mut self, index: Index) { - let shape = index.primitive(&self.graph).shape(); + let shape = index.primitive(self).shape(); let removed_element = self.rtree.remove(&RTreeWrapper::new(shape, index)); debug_assert!(removed_element.is_some()); } @@ -459,7 +457,7 @@ impl Layout { fn test_envelopes(&self) -> bool { !self.rtree.iter().any(|wrapper| { let index = wrapper.data; - let shape = index.primitive(&self.graph).shape(); + let shape = index.primitive(self).shape(); let wrapper = RTreeWrapper::new(shape, index); !self .rtree diff --git a/src/main.rs b/src/main.rs index 5fcdd1f..a01bf81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -524,8 +524,8 @@ fn render_times( if let Some(ref mesh) = mesh { for edge in mesh.edge_references() { - let start_point = edge.source().primitive(&layout.graph).shape().center(); - let end_point = edge.target().primitive(&layout.graph).shape().center(); + let start_point = edge.source().primitive(layout).shape().center(); + let end_point = edge.target().primitive(layout).shape().center(); let color = if path.contains(&edge.source()) && path.contains(&edge.target()) { Color::RGB(250, 250, 0) diff --git a/src/mesh.rs b/src/mesh.rs index dfb734a..3a1c05c 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -65,7 +65,7 @@ impl Mesh { pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> { for node in layout.nodes() { - let center = node.primitive(&layout.graph).shape().center(); + let center = node.primitive(layout).shape().center(); match node { Index::FixedDot(fixed_dot) => { diff --git a/src/primitive.rs b/src/primitive.rs index a2fe421..e52a6b4 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -6,24 +6,25 @@ use petgraph::Direction::{Incoming, Outgoing}; use crate::graph::{ DotIndex, FixedBendIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, - GenericIndex, GetEnds, GetNet, GetNodeIndex, GetWidth, Index, Interior, Label, LooseBendIndex, - LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive, - Retag, Weight, + GenericIndex, GetBand, GetEnds, GetNet, GetNodeIndex, GetWidth, Index, Interior, Label, + LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, + MakePrimitive, Retag, Weight, }; +use crate::layout::Layout; use crate::math::{self, Circle}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; use crate::traverser::OutwardRailTraverser; #[enum_dispatch] -pub trait GetGraph { - fn graph(&self) -> &StableDiGraph; +pub trait GetLayout { + fn layout(&self) -> &Layout; } #[enum_dispatch] -pub trait GetConnectable: GetNet + GetGraph { +pub trait GetConnectable: GetNet + GetLayout { fn connectable(&self, index: Index) -> bool { let this = self.net(); - let other = index.primitive(self.graph()).net(); + let other = index.primitive(self.layout()).net(); (this == other) || this == -1 || other == -1 } @@ -52,19 +53,31 @@ pub trait GetOtherEnd>: GetEnds pub trait TraverseOutward: GetFirstRail { fn traverse_outward(&self) -> OutwardRailTraverser { - OutwardRailTraverser::new(self.first_rail(), self.graph()) + OutwardRailTraverser::new(self.first_rail(), self.layout()) } } -pub trait GetFirstRail: GetGraph + GetNodeIndex { +pub trait GetFirstRail: GetLayout + GetNodeIndex { fn first_rail(&self) -> Option { - self.graph() + self.layout() + .graph .neighbors_directed(self.node_index(), Incoming) - .filter(|ni| self.graph().find_edge(self.node_index(), *ni).is_some()) + .filter(|ni| { + self.layout() + .graph + .find_edge(self.node_index(), *ni) + .is_some() + }) .filter(|ni| { matches!( - self.graph() - .edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) + self.layout() + .graph + .edge_weight( + self.layout() + .graph + .find_edge(self.node_index(), *ni) + .unwrap() + ) .unwrap(), Label::Core ) @@ -74,14 +87,21 @@ pub trait GetFirstRail: GetGraph + GetNodeIndex { } } -pub trait GetCore: GetGraph + GetNodeIndex { +pub trait GetCore: GetLayout + GetNodeIndex { fn core(&self) -> FixedDotIndex { - self.graph() + self.layout() + .graph .neighbors(self.node_index()) .filter(|ni| { matches!( - self.graph() - .edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) + self.layout() + .graph + .edge_weight( + self.layout() + .graph + .find_edge(self.node_index(), *ni) + .unwrap() + ) .unwrap(), Label::Core ) @@ -92,14 +112,21 @@ pub trait GetCore: GetGraph + GetNodeIndex { } } -pub trait GetInnerOuter: GetGraph + GetNodeIndex { +pub trait GetInnerOuter: GetLayout + GetNodeIndex { fn inner(&self) -> Option { - self.graph() + self.layout() + .graph .neighbors_directed(self.node_index(), Incoming) .filter(|ni| { matches!( - self.graph() - .edge_weight(self.graph().find_edge(*ni, self.node_index()).unwrap()) + self.layout() + .graph + .edge_weight( + self.layout() + .graph + .find_edge(*ni, self.node_index()) + .unwrap() + ) .unwrap(), Label::Outer ) @@ -109,12 +136,19 @@ pub trait GetInnerOuter: GetGraph + GetNodeIndex { } fn outer(&self) -> Option { - self.graph() + self.layout() + .graph .neighbors_directed(self.node_index(), Outgoing) .filter(|ni| { matches!( - self.graph() - .edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) + self.layout() + .graph + .edge_weight( + self.layout() + .graph + .find_edge(self.node_index(), *ni) + .unwrap() + ) .unwrap(), Label::Outer ) @@ -138,7 +172,31 @@ macro_rules! impl_primitive { }; } -#[enum_dispatch(GetNet, GetWidth, GetGraph, GetConnectable, MakeShape)] +macro_rules! impl_fixed_primitive { + ($primitive_struct:ident, $weight_struct:ident) => { + impl_primitive!($primitive_struct, $weight_struct); + + impl<'a> GetNet for $primitive_struct<'a> { + fn net(&self) -> i64 { + self.weight().net() + } + } + }; +} + +macro_rules! impl_loose_primitive { + ($primitive_struct:ident, $weight_struct:ident) => { + impl_primitive!($primitive_struct, $weight_struct); + + impl<'a> GetNet for $primitive_struct<'a> { + fn net(&self) -> i64 { + self.layout().bands[self.weight().band()].net + } + } + }; +} + +#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape)] pub enum Primitive<'a> { FixedDot(FixedDot<'a>), LooseDot(LooseDot<'a>), @@ -151,26 +209,33 @@ pub enum Primitive<'a> { #[derive(Debug)] pub struct GenericPrimitive<'a, W> { pub index: GenericIndex, - graph: &'a StableDiGraph, + layout: &'a Layout, } impl<'a, W> GenericPrimitive<'a, W> { - pub fn new(index: GenericIndex, graph: &'a StableDiGraph) -> Self { - Self { index, graph } + pub fn new(index: GenericIndex, layout: &'a Layout) -> Self { + Self { index, layout } } fn tagged_weight(&self) -> Weight { - *self.graph.node_weight(self.index.node_index()).unwrap() + *self + .layout + .graph + .node_weight(self.index.node_index()) + .unwrap() } fn adjacents(&self) -> Vec> { - self.graph + self.layout + .graph .neighbors_undirected(self.index.node_index()) .filter(|ni| { matches!( - self.graph + self.layout + .graph .edge_weight( - self.graph + self.layout + .graph .find_edge_undirected(self.index.node_index(), *ni) .unwrap() .0, @@ -183,7 +248,7 @@ impl<'a, W> GenericPrimitive<'a, W> { } fn primitive(&self, index: GenericIndex) -> GenericPrimitive { - GenericPrimitive::new(index, &self.graph) + GenericPrimitive::new(index, &self.layout) } } @@ -193,9 +258,9 @@ impl<'a, W> Interior for GenericPrimitive<'a, W> { } } -impl<'a, W> GetGraph for GenericPrimitive<'a, W> { - fn graph(&self) -> &StableDiGraph { - self.graph +impl<'a, W> GetLayout for GenericPrimitive<'a, W> { + fn layout(&self) -> &Layout { + self.layout } } @@ -205,19 +270,7 @@ impl<'a, W> GetNodeIndex for GenericPrimitive<'a, W> { } } -impl<'a, W: GetNet> GetConnectable for GenericPrimitive<'a, W> where - GenericPrimitive<'a, W>: GetWeight -{ -} - -impl<'a, W: GetNet> GetNet for GenericPrimitive<'a, W> -where - GenericPrimitive<'a, W>: GetWeight, -{ - fn net(&self) -> i64 { - self.weight().net() - } -} +impl<'a, W> GetConnectable for GenericPrimitive<'a, W> where GenericPrimitive<'a, W>: GetNet {} impl<'a, W: GetWidth> GetWidth for GenericPrimitive<'a, W> where @@ -229,7 +282,7 @@ where } pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>; -impl_primitive!(FixedDot, FixedDotWeight); +impl_fixed_primitive!(FixedDot, FixedDotWeight); impl<'a> MakeShape for FixedDot<'a> { fn shape(&self) -> Shape { @@ -243,17 +296,20 @@ impl<'a> TraverseOutward for FixedDot<'a> {} impl<'a> GetFirstRail for FixedDot<'a> {} pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>; -impl_primitive!(LooseDot, LooseDotWeight); +impl_loose_primitive!(LooseDot, LooseDotWeight); impl<'a> LooseDot<'a> { pub fn seg(&self) -> Option { - self.graph + self.layout + .graph .neighbors_undirected(self.index.node_index()) .filter(|ni| { matches!( - self.graph + self.layout + .graph .edge_weight( - self.graph + self.layout + .graph .find_edge_undirected(self.index.node_index(), *ni) .unwrap() .0, @@ -262,19 +318,27 @@ impl<'a> LooseDot<'a> { Label::Adjacent ) }) - .filter(|ni| matches!(self.graph.node_weight(*ni).unwrap(), Weight::LooseSeg(..))) + .filter(|ni| { + matches!( + self.layout.graph.node_weight(*ni).unwrap(), + Weight::LooseSeg(..) + ) + }) .map(|ni| LooseSegIndex::new(ni)) .next() } pub fn bend(&self) -> LooseBendIndex { - self.graph + self.layout + .graph .neighbors_undirected(self.index.node_index()) .filter(|ni| { matches!( - self.graph + self.layout + .graph .edge_weight( - self.graph + self.layout + .graph .find_edge_undirected(self.index.node_index(), *ni) .unwrap() .0, @@ -283,7 +347,12 @@ impl<'a> LooseDot<'a> { Label::Adjacent ) }) - .filter(|ni| matches!(self.graph.node_weight(*ni).unwrap(), Weight::LooseBend(..))) + .filter(|ni| { + matches!( + self.layout.graph.node_weight(*ni).unwrap(), + Weight::LooseBend(..) + ) + }) .map(|ni| LooseBendIndex::new(ni)) .next() .unwrap() @@ -299,7 +368,7 @@ impl<'a> MakeShape for LooseDot<'a> { } pub type FixedSeg<'a> = GenericPrimitive<'a, FixedSegWeight>; -impl_primitive!(FixedSeg, FixedSegWeight); +impl_fixed_primitive!(FixedSeg, FixedSegWeight); impl<'a> MakeShape for FixedSeg<'a> { fn shape(&self) -> Shape { @@ -322,7 +391,7 @@ impl<'a> GetEnds for FixedSeg<'a> { impl<'a> GetOtherEnd for FixedSeg<'a> {} pub type LooseSeg<'a> = GenericPrimitive<'a, LooseSegWeight>; -impl_primitive!(LooseSeg, LooseSegWeight); +impl_loose_primitive!(LooseSeg, LooseSegWeight); impl<'a> MakeShape for LooseSeg<'a> { fn shape(&self) -> Shape { @@ -347,9 +416,9 @@ impl<'a> GetWidth for LooseSeg<'a> { impl<'a> GetEnds for LooseSeg<'a> { fn ends(&self) -> (DotIndex, LooseDotIndex) { let v = self.adjacents(); - if let Weight::FixedDot(..) = self.graph.node_weight(v[0]).unwrap() { + if let Weight::FixedDot(..) = self.layout.graph.node_weight(v[0]).unwrap() { (FixedDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1])) - } else if let Weight::FixedDot(..) = self.graph.node_weight(v[1]).unwrap() { + } else if let Weight::FixedDot(..) = self.layout.graph.node_weight(v[1]).unwrap() { (FixedDotIndex::new(v[1]).into(), LooseDotIndex::new(v[0])) } else { (LooseDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1])) @@ -360,7 +429,7 @@ impl<'a> GetEnds for LooseSeg<'a> { impl<'a> GetOtherEnd for LooseSeg<'a> {} pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>; -impl_primitive!(FixedBend, FixedBendWeight); +impl_fixed_primitive!(FixedBend, FixedBendWeight); impl<'a> FixedBend<'a> { fn inner_radius(&self) -> f64 { @@ -411,7 +480,7 @@ impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actu //impl<'a> GetInnerOuter for FixedBend<'a> {} pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>; -impl_primitive!(LooseBend, LooseBendWeight); +impl_loose_primitive!(LooseBend, LooseBendWeight); impl<'a> LooseBend<'a> { fn inner_radius(&self) -> f64 { diff --git a/src/router.rs b/src/router.rs index 0ba1292..aea3023 100644 --- a/src/router.rs +++ b/src/router.rs @@ -94,7 +94,7 @@ impl Router { mesh.generate(&self.layout)?; let mut tracer = self.tracer(&mesh); - let trace = tracer.start(from); + let trace = tracer.start(from, 3.0); let (_cost, _path) = astar( &mesh, diff --git a/src/segbend.rs b/src/segbend.rs index 8729a9a..4755ccf 100644 --- a/src/segbend.rs +++ b/src/segbend.rs @@ -4,6 +4,7 @@ use crate::{ graph::{ GetEnds, Index, Interior, Label, LooseBendIndex, LooseDotIndex, LooseSegIndex, Weight, }, + layout::Layout, primitive::{GetOtherEnd, LooseBend, LooseDot}, }; @@ -15,10 +16,10 @@ pub struct Segbend { } impl Segbend { - pub fn from_dot(dot: LooseDotIndex, graph: &StableDiGraph) -> Self { - let bend = LooseDot::new(dot, graph).bend(); - let dot = LooseBend::new(bend, graph).other_end(dot); - let seg = LooseDot::new(dot, graph).seg().unwrap(); + 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 seg = LooseDot::new(dot, layout).seg().unwrap(); Self { bend, dot, seg } } } diff --git a/src/tracer.rs b/src/tracer.rs index a323caf..ce4a7a0 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -2,8 +2,8 @@ use contracts::debug_ensures; use crate::{ draw::{BareHead, Draw, Head, SegbendHead}, - graph::{FixedDotIndex, LooseBendIndex}, - layout::Layout, + graph::{FixedDotIndex, GetNet, LooseBendIndex}, + layout::{Band, Layout}, mesh::{Mesh, VertexIndex}, primitive::{GetFirstRail, GetInnerOuter}, rules::Rules, @@ -30,10 +30,14 @@ impl<'a> Tracer<'a> { } } - pub fn start(&mut self, from: FixedDotIndex) -> Trace { + pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { + let band = self.layout.bands.insert(Band { + width, + net: self.layout.primitive(from).net(), + }); Trace { path: vec![from.into()], - head: BareHead { dot: from }.into(), + head: BareHead { dot: from, band }.into(), } } diff --git a/src/traverser.rs b/src/traverser.rs index 4825362..85bfff0 100644 --- a/src/traverser.rs +++ b/src/traverser.rs @@ -2,20 +2,18 @@ use petgraph::stable_graph::StableDiGraph; use crate::{ graph::{Label, LooseBendIndex, Weight}, + layout::Layout, primitive::{GenericPrimitive, GetInnerOuter}, }; pub struct OutwardRailTraverser<'a> { rail: Option, - graph: &'a StableDiGraph, + layout: &'a Layout, } impl<'a> OutwardRailTraverser<'a> { - pub fn new( - rail: Option, - graph: &'a StableDiGraph, - ) -> Self { - Self { rail, graph } + pub fn new(rail: Option, layout: &'a Layout) -> Self { + Self { rail, layout } } } @@ -24,7 +22,7 @@ impl<'a> Iterator for OutwardRailTraverser<'a> { fn next(&mut self) -> Option { self.rail.map(|rail| { - self.rail = GenericPrimitive::new(rail, self.graph).outer(); + self.rail = GenericPrimitive::new(rail, self.layout).outer(); rail }) }