graph,layout,primitive: store band index instead of net in loose weights

This commit is contained in:
Mikolaj Wielgus 2023-12-15 01:42:09 +00:00
parent b8f6b32341
commit 294e6c4f72
12 changed files with 265 additions and 145 deletions

View File

@ -14,6 +14,9 @@ version = "0.11.0"
[dependencies.petgraph] [dependencies.petgraph]
version = "0.6.3" version = "0.6.3"
[dependencies.slab]
version = "0.4.9"
[dependencies.spade] [dependencies.spade]
version = "2.2.0" version = "2.2.0"

View File

@ -4,11 +4,12 @@ use geo::{EuclideanLength, Point};
use crate::{ use crate::{
graph::{ graph::{
BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetEnds, GetNet, Index, LooseBendIndex, BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetBand, GetEnds, GetNet, Index,
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive, LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight,
MakePrimitive,
}, },
guide::Guide, guide::Guide,
layout::Layout, layout::{Band, Layout},
math::Circle, math::Circle,
primitive::{GetOtherEnd, GetWeight}, primitive::{GetOtherEnd, GetWeight},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
@ -18,6 +19,7 @@ use crate::{
#[enum_dispatch] #[enum_dispatch]
pub trait HeadTrait { pub trait HeadTrait {
fn dot(&self) -> DotIndex; fn dot(&self) -> DotIndex;
fn band(&self) -> usize;
} }
#[enum_dispatch(HeadTrait)] #[enum_dispatch(HeadTrait)]
@ -30,24 +32,34 @@ pub enum Head {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct BareHead { pub struct BareHead {
pub dot: FixedDotIndex, pub dot: FixedDotIndex,
pub band: usize,
} }
impl HeadTrait for BareHead { impl HeadTrait for BareHead {
fn dot(&self) -> DotIndex { fn dot(&self) -> DotIndex {
self.dot.into() self.dot.into()
} }
fn band(&self) -> usize {
self.band
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct SegbendHead { pub struct SegbendHead {
pub dot: LooseDotIndex, pub dot: LooseDotIndex,
pub segbend: Segbend, pub segbend: Segbend,
pub band: usize,
} }
impl HeadTrait for SegbendHead { impl HeadTrait for SegbendHead {
fn dot(&self) -> DotIndex { fn dot(&self) -> DotIndex {
self.dot.into() self.dot.into()
} }
fn band(&self) -> usize {
self.band
}
} }
pub struct Draw<'a> { pub struct Draw<'a> {
@ -72,7 +84,7 @@ impl<'a> Draw<'a> {
.head_into_dot_segment(&head, into, width)?; .head_into_dot_segment(&head, into, width)?;
let head = self.extend_head(head, tangent.start_point())?; 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() { match head.dot() {
DotIndex::Fixed(dot) => { DotIndex::Fixed(dot) => {
@ -80,8 +92,11 @@ impl<'a> Draw<'a> {
.add_fixed_seg(into.into(), dot, FixedSegWeight { net, width })?; .add_fixed_seg(into.into(), dot, FixedSegWeight { net, width })?;
} }
DotIndex::Loose(dot) => { DotIndex::Loose(dot) => {
self.layout self.layout.add_loose_seg(
.add_loose_seg(into.into(), dot, LooseSegWeight { net })?; into.into(),
dot,
LooseSegWeight { band: head.band() },
)?;
} }
} }
Ok(()) Ok(())
@ -111,9 +126,12 @@ impl<'a> Draw<'a> {
let head = self.extend_head(head, tangent.start_point())?; let head = self.extend_head(head, tangent.start_point())?;
let _to_head = self.extend_head(to_head.into(), tangent.end_point())?; let _to_head = self.extend_head(to_head.into(), tangent.end_point())?;
let net = head.dot().primitive(&self.layout.graph).net(); let net = head.dot().primitive(self.layout).net();
self.layout self.layout.add_loose_seg(
.add_loose_seg(head.dot(), into.into(), LooseSegWeight { net })?; head.dot(),
into.into(),
LooseSegWeight { band: head.band() },
)?;
Ok(()) Ok(())
} }
@ -224,23 +242,26 @@ impl<'a> Draw<'a> {
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
let net = head.dot().primitive(&self.layout.graph).net();
let segbend = self.layout.add_segbend( let segbend = self.layout.add_segbend(
head.dot(), head.dot(),
around, around,
LooseDotWeight { LooseDotWeight {
net, band: head.band(),
circle: Circle { circle: Circle {
pos: to, pos: to,
r: width / 2.0, r: width / 2.0,
}, },
}, },
LooseSegWeight { net }, LooseSegWeight { band: head.band() },
LooseBendWeight { net, cw }, LooseBendWeight {
band: head.band(),
cw,
},
)?; )?;
Ok(SegbendHead { Ok(SegbendHead {
dot: self.layout.primitive(segbend.bend).other_end(segbend.dot), dot: self.layout.primitive(segbend.bend).other_end(segbend.dot),
segbend, segbend,
band: head.band(),
}) })
} }
@ -251,11 +272,12 @@ impl<'a> Draw<'a> {
.layout .layout
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_end(head.segbend.dot.into()); .other_end(head.segbend.dot.into());
let band = head.band;
self.layout.remove_interior(&head.segbend); self.layout.remove_interior(&head.segbend);
self.layout.remove(head.dot().into()); 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()))] #[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);*/ self.layout.reposition_bend(bend, from, to);*/
} }
fn head(&self, dot: DotIndex) -> Head { fn head(&self, dot: DotIndex, band: usize) -> Head {
match dot { 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(), DotIndex::Loose(fixed) => self.segbend_head(fixed).into(),
} }
} }
@ -285,11 +307,15 @@ impl<'a> Draw<'a> {
SegbendHead { SegbendHead {
dot, dot,
segbend: self.layout.segbend(dot), segbend: self.layout.segbend(dot),
band: self.layout.primitive(dot).weight().band(),
} }
} }
fn rear_head(&self, dot: LooseDotIndex) -> Head { 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 { fn rear(&self, head: SegbendHead) -> DotIndex {

View File

@ -6,6 +6,7 @@ use std::{
}; };
use crate::{ use crate::{
layout::Layout,
math::Circle, math::Circle,
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
}; };
@ -33,6 +34,11 @@ pub trait GetNetMut {
fn net_mut(&mut self) -> &mut i64; fn net_mut(&mut self) -> &mut i64;
} }
#[enum_dispatch]
pub trait GetBand {
fn band(&self) -> usize;
}
#[enum_dispatch] #[enum_dispatch]
pub trait GetWidth { pub trait GetWidth {
fn width(&self) -> f64; 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 { impl GetNet for $weight_struct {
fn net(&self) -> i64 { fn net(&self) -> i64 {
self.net self.net
@ -60,21 +80,22 @@ macro_rules! impl_weight {
&mut self.net &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 { impl GetBand for $weight_struct {
fn primitive<'a>( fn band(&self) -> usize {
&self, self.band
graph: &'a StableDiGraph<Weight, Label, usize>,
) -> Primitive<'a> {
Primitive::$weight_variant(GenericPrimitive::new(*self, graph))
} }
} }
}; };
} }
#[enum_dispatch(Retag, GetNet, GetNetMut)] #[enum_dispatch(Retag)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum Weight { pub enum Weight {
FixedDot(FixedDotWeight), FixedDot(FixedDotWeight),
@ -144,7 +165,7 @@ impl From<BendIndex> for Index {
} }
} }
pub trait DotWeight: GetNet + GetWidth + Into<Weight> + Copy {} pub trait DotWeight: GetWidth + Into<Weight> + Copy {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedDotWeight { pub struct FixedDotWeight {
@ -152,7 +173,7 @@ pub struct FixedDotWeight {
pub circle: Circle, pub circle: Circle,
} }
impl_weight!(FixedDotWeight, FixedDot, FixedDotIndex); impl_fixed_weight!(FixedDotWeight, FixedDot, FixedDotIndex);
impl DotWeight for FixedDotWeight {} impl DotWeight for FixedDotWeight {}
impl GetWidth for FixedDotWeight { impl GetWidth for FixedDotWeight {
@ -163,11 +184,11 @@ impl GetWidth for FixedDotWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LooseDotWeight { pub struct LooseDotWeight {
pub net: i64, pub band: usize,
pub circle: Circle, pub circle: Circle,
} }
impl_weight!(LooseDotWeight, LooseDot, LooseDotIndex); impl_loose_weight!(LooseDotWeight, LooseDot, LooseDotIndex);
impl DotWeight for LooseDotWeight {} impl DotWeight for LooseDotWeight {}
impl GetWidth for LooseDotWeight { impl GetWidth for LooseDotWeight {
@ -176,7 +197,7 @@ impl GetWidth for LooseDotWeight {
} }
} }
pub trait SegWeight: GetNet + Into<Weight> + Copy {} pub trait SegWeight: Into<Weight> + Copy {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedSegWeight { pub struct FixedSegWeight {
@ -184,7 +205,7 @@ pub struct FixedSegWeight {
pub width: f64, pub width: f64,
} }
impl_weight!(FixedSegWeight, FixedSeg, FixedSegIndex); impl_fixed_weight!(FixedSegWeight, FixedSeg, FixedSegIndex);
impl SegWeight for FixedSegWeight {} impl SegWeight for FixedSegWeight {}
impl GetWidth for FixedSegWeight { impl GetWidth for FixedSegWeight {
@ -195,13 +216,13 @@ impl GetWidth for FixedSegWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LooseSegWeight { pub struct LooseSegWeight {
pub net: i64, pub band: usize,
} }
impl_weight!(LooseSegWeight, LooseSeg, LooseSegIndex); impl_loose_weight!(LooseSegWeight, LooseSeg, LooseSegIndex);
impl SegWeight for LooseSegWeight {} impl SegWeight for LooseSegWeight {}
pub trait BendWeight: GetNet + Into<Weight> + Copy {} pub trait BendWeight: Into<Weight> + Copy {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedBendWeight { pub struct FixedBendWeight {
@ -210,7 +231,7 @@ pub struct FixedBendWeight {
pub cw: bool, pub cw: bool,
} }
impl_weight!(FixedBendWeight, FixedBend, FixedBendIndex); impl_fixed_weight!(FixedBendWeight, FixedBend, FixedBendIndex);
impl BendWeight for FixedBendWeight {} impl BendWeight for FixedBendWeight {}
impl GetWidth for FixedBendWeight { impl GetWidth for FixedBendWeight {
@ -221,11 +242,11 @@ impl GetWidth for FixedBendWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LooseBendWeight { pub struct LooseBendWeight {
pub net: i64, pub band: usize,
pub cw: bool, pub cw: bool,
} }
impl_weight!(LooseBendWeight, LooseBend, LooseBendIndex); impl_loose_weight!(LooseBendWeight, LooseBend, LooseBendIndex);
impl BendWeight for LooseBendWeight {} impl BendWeight for LooseBendWeight {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -242,7 +263,7 @@ pub trait GetNodeIndex {
#[enum_dispatch] #[enum_dispatch]
pub trait MakePrimitive { pub trait MakePrimitive {
fn primitive<'a>(&self, graph: &'a StableDiGraph<Weight, Label, usize>) -> Primitive<'a>; fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>;
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]

View File

@ -117,7 +117,7 @@ impl<'a, 'b> Guide<'a, 'b> {
match *head { match *head {
Head::Bare(head) => Circle { 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, r: 0.0,
}, },
Head::Segbend(head) => { Head::Segbend(head) => {
@ -134,7 +134,7 @@ impl<'a, 'b> Guide<'a, 'b> {
} }
fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { 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 { Circle {
pos: shape.center(), pos: shape.center(),
r: shape.width() / 2.0 r: shape.width() / 2.0
@ -145,7 +145,7 @@ impl<'a, 'b> Guide<'a, 'b> {
} }
fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { 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 { Circle {
pos: shape.center(), pos: shape.center(),
r: shape.width() / 2.0 + width + self.rules.ruleset(self.conditions).clearance.min, r: shape.width() / 2.0 + width + self.rules.ruleset(self.conditions).clearance.min,

View File

@ -5,6 +5,7 @@ use petgraph::visit::EdgeRef;
use petgraph::Direction::Incoming; use petgraph::Direction::Incoming;
use rstar::primitives::GeomWithData; use rstar::primitives::GeomWithData;
use rstar::{RTree, RTreeObject}; use rstar::{RTree, RTreeObject};
use slab::Slab;
use crate::graph::{ use crate::graph::{
BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex, BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex,
@ -18,8 +19,16 @@ use crate::shape::{Shape, ShapeTrait};
pub type RTreeWrapper = GeomWithData<Shape, Index>; pub type RTreeWrapper = GeomWithData<Shape, Index>;
#[derive(Debug)]
pub struct Band {
pub net: i64,
pub width: f64,
}
#[derive(Debug)]
pub struct Layout { pub struct Layout {
rtree: RTree<RTreeWrapper>, rtree: RTree<RTreeWrapper>,
pub bands: Slab<Band>,
pub graph: StableDiGraph<Weight, Label, usize>, pub graph: StableDiGraph<Weight, Label, usize>,
} }
@ -29,6 +38,7 @@ impl Layout {
pub fn new() -> Self { pub fn new() -> Self {
Layout { Layout {
rtree: RTree::new(), rtree: RTree::new(),
bands: Slab::new(),
graph: StableDiGraph::default(), graph: StableDiGraph::default(),
} }
} }
@ -178,17 +188,6 @@ impl Layout {
self.insert_into_rtree(seg.into()); self.insert_into_rtree(seg.into());
self.fail_and_remove_if_collides_except(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) Ok(seg)
} }
@ -341,7 +340,7 @@ impl Layout {
}*/ }*/
pub fn segbend(&self, dot: LooseDotIndex) -> Segbend { 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()))] #[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<Item = Shape> + '_ { pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
self.node_indices() self.node_indices().map(|ni| ni.primitive(self).shape())
.map(|ni| ni.primitive(&self.graph).shape())
} }
pub fn node_count(&self) -> usize { pub fn node_count(&self) -> usize {
@ -421,17 +419,17 @@ impl Layout {
} }
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W> { pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W> {
GenericPrimitive::new(index, &self.graph) GenericPrimitive::new(index, self)
} }
fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> { fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> {
let shape = index.primitive(&self.graph).shape(); let shape = index.primitive(self).shape();
self.rtree self.rtree
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| { .filter(|wrapper| {
let other_index = wrapper.data; 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| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom())) .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.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn insert_into_rtree(&mut self, index: Index) { 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)); self.rtree.insert(RTreeWrapper::new(shape, index));
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn remove_from_rtree(&mut self, index: Index) { 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)); let removed_element = self.rtree.remove(&RTreeWrapper::new(shape, index));
debug_assert!(removed_element.is_some()); debug_assert!(removed_element.is_some());
} }
@ -459,7 +457,7 @@ impl Layout {
fn test_envelopes(&self) -> bool { fn test_envelopes(&self) -> bool {
!self.rtree.iter().any(|wrapper| { !self.rtree.iter().any(|wrapper| {
let index = wrapper.data; let index = wrapper.data;
let shape = index.primitive(&self.graph).shape(); let shape = index.primitive(self).shape();
let wrapper = RTreeWrapper::new(shape, index); let wrapper = RTreeWrapper::new(shape, index);
!self !self
.rtree .rtree

View File

@ -524,8 +524,8 @@ fn render_times(
if let Some(ref mesh) = mesh { if let Some(ref mesh) = mesh {
for edge in mesh.edge_references() { for edge in mesh.edge_references() {
let start_point = edge.source().primitive(&layout.graph).shape().center(); let start_point = edge.source().primitive(layout).shape().center();
let end_point = edge.target().primitive(&layout.graph).shape().center(); let end_point = edge.target().primitive(layout).shape().center();
let color = if path.contains(&edge.source()) && path.contains(&edge.target()) { let color = if path.contains(&edge.source()) && path.contains(&edge.target()) {
Color::RGB(250, 250, 0) Color::RGB(250, 250, 0)

View File

@ -65,7 +65,7 @@ impl Mesh {
pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> { pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> {
for node in layout.nodes() { for node in layout.nodes() {
let center = node.primitive(&layout.graph).shape().center(); let center = node.primitive(layout).shape().center();
match node { match node {
Index::FixedDot(fixed_dot) => { Index::FixedDot(fixed_dot) => {

View File

@ -6,24 +6,25 @@ use petgraph::Direction::{Incoming, Outgoing};
use crate::graph::{ use crate::graph::{
DotIndex, FixedBendIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, DotIndex, FixedBendIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight,
GenericIndex, GetEnds, GetNet, GetNodeIndex, GetWidth, Index, Interior, Label, LooseBendIndex, GenericIndex, GetBand, GetEnds, GetNet, GetNodeIndex, GetWidth, Index, Interior, Label,
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive, LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight,
Retag, Weight, MakePrimitive, Retag, Weight,
}; };
use crate::layout::Layout;
use crate::math::{self, Circle}; use crate::math::{self, Circle};
use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait};
use crate::traverser::OutwardRailTraverser; use crate::traverser::OutwardRailTraverser;
#[enum_dispatch] #[enum_dispatch]
pub trait GetGraph { pub trait GetLayout {
fn graph(&self) -> &StableDiGraph<Weight, Label, usize>; fn layout(&self) -> &Layout;
} }
#[enum_dispatch] #[enum_dispatch]
pub trait GetConnectable: GetNet + GetGraph { pub trait GetConnectable: GetNet + GetLayout {
fn connectable(&self, index: Index) -> bool { fn connectable(&self, index: Index) -> bool {
let this = self.net(); let this = self.net();
let other = index.primitive(self.graph()).net(); let other = index.primitive(self.layout()).net();
(this == other) || this == -1 || other == -1 (this == other) || this == -1 || other == -1
} }
@ -52,19 +53,31 @@ pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
pub trait TraverseOutward: GetFirstRail { pub trait TraverseOutward: GetFirstRail {
fn traverse_outward(&self) -> OutwardRailTraverser { 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<LooseBendIndex> { fn first_rail(&self) -> Option<LooseBendIndex> {
self.graph() self.layout()
.graph
.neighbors_directed(self.node_index(), Incoming) .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| { .filter(|ni| {
matches!( matches!(
self.graph() self.layout()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) .graph
.edge_weight(
self.layout()
.graph
.find_edge(self.node_index(), *ni)
.unwrap()
)
.unwrap(), .unwrap(),
Label::Core 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 { fn core(&self) -> FixedDotIndex {
self.graph() self.layout()
.graph
.neighbors(self.node_index()) .neighbors(self.node_index())
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph() self.layout()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) .graph
.edge_weight(
self.layout()
.graph
.find_edge(self.node_index(), *ni)
.unwrap()
)
.unwrap(), .unwrap(),
Label::Core 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<LooseBendIndex> { fn inner(&self) -> Option<LooseBendIndex> {
self.graph() self.layout()
.graph
.neighbors_directed(self.node_index(), Incoming) .neighbors_directed(self.node_index(), Incoming)
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph() self.layout()
.edge_weight(self.graph().find_edge(*ni, self.node_index()).unwrap()) .graph
.edge_weight(
self.layout()
.graph
.find_edge(*ni, self.node_index())
.unwrap()
)
.unwrap(), .unwrap(),
Label::Outer Label::Outer
) )
@ -109,12 +136,19 @@ pub trait GetInnerOuter: GetGraph + GetNodeIndex {
} }
fn outer(&self) -> Option<LooseBendIndex> { fn outer(&self) -> Option<LooseBendIndex> {
self.graph() self.layout()
.graph
.neighbors_directed(self.node_index(), Outgoing) .neighbors_directed(self.node_index(), Outgoing)
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph() self.layout()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) .graph
.edge_weight(
self.layout()
.graph
.find_edge(self.node_index(), *ni)
.unwrap()
)
.unwrap(), .unwrap(),
Label::Outer 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> { pub enum Primitive<'a> {
FixedDot(FixedDot<'a>), FixedDot(FixedDot<'a>),
LooseDot(LooseDot<'a>), LooseDot(LooseDot<'a>),
@ -151,26 +209,33 @@ pub enum Primitive<'a> {
#[derive(Debug)] #[derive(Debug)]
pub struct GenericPrimitive<'a, W> { pub struct GenericPrimitive<'a, W> {
pub index: GenericIndex<W>, pub index: GenericIndex<W>,
graph: &'a StableDiGraph<Weight, Label, usize>, layout: &'a Layout,
} }
impl<'a, W> GenericPrimitive<'a, W> { impl<'a, W> GenericPrimitive<'a, W> {
pub fn new(index: GenericIndex<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self { pub fn new(index: GenericIndex<W>, layout: &'a Layout) -> Self {
Self { index, graph } Self { index, layout }
} }
fn tagged_weight(&self) -> Weight { 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<NodeIndex<usize>> { fn adjacents(&self) -> Vec<NodeIndex<usize>> {
self.graph self.layout
.graph
.neighbors_undirected(self.index.node_index()) .neighbors_undirected(self.index.node_index())
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph self.layout
.graph
.edge_weight( .edge_weight(
self.graph self.layout
.graph
.find_edge_undirected(self.index.node_index(), *ni) .find_edge_undirected(self.index.node_index(), *ni)
.unwrap() .unwrap()
.0, .0,
@ -183,7 +248,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
} }
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> { fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> {
GenericPrimitive::new(index, &self.graph) GenericPrimitive::new(index, &self.layout)
} }
} }
@ -193,9 +258,9 @@ impl<'a, W> Interior<Index> for GenericPrimitive<'a, W> {
} }
} }
impl<'a, W> GetGraph for GenericPrimitive<'a, W> { impl<'a, W> GetLayout for GenericPrimitive<'a, W> {
fn graph(&self) -> &StableDiGraph<Weight, Label, usize> { fn layout(&self) -> &Layout {
self.graph self.layout
} }
} }
@ -205,19 +270,7 @@ impl<'a, W> GetNodeIndex for GenericPrimitive<'a, W> {
} }
} }
impl<'a, W: GetNet> GetConnectable for GenericPrimitive<'a, W> where impl<'a, W> GetConnectable for GenericPrimitive<'a, W> where GenericPrimitive<'a, W>: GetNet {}
GenericPrimitive<'a, W>: GetWeight<W>
{
}
impl<'a, W: GetNet> GetNet for GenericPrimitive<'a, W>
where
GenericPrimitive<'a, W>: GetWeight<W>,
{
fn net(&self) -> i64 {
self.weight().net()
}
}
impl<'a, W: GetWidth> GetWidth for GenericPrimitive<'a, W> impl<'a, W: GetWidth> GetWidth for GenericPrimitive<'a, W>
where where
@ -229,7 +282,7 @@ where
} }
pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>; pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>;
impl_primitive!(FixedDot, FixedDotWeight); impl_fixed_primitive!(FixedDot, FixedDotWeight);
impl<'a> MakeShape for FixedDot<'a> { impl<'a> MakeShape for FixedDot<'a> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
@ -243,17 +296,20 @@ impl<'a> TraverseOutward for FixedDot<'a> {}
impl<'a> GetFirstRail for FixedDot<'a> {} impl<'a> GetFirstRail for FixedDot<'a> {}
pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>; pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>;
impl_primitive!(LooseDot, LooseDotWeight); impl_loose_primitive!(LooseDot, LooseDotWeight);
impl<'a> LooseDot<'a> { impl<'a> LooseDot<'a> {
pub fn seg(&self) -> Option<LooseSegIndex> { pub fn seg(&self) -> Option<LooseSegIndex> {
self.graph self.layout
.graph
.neighbors_undirected(self.index.node_index()) .neighbors_undirected(self.index.node_index())
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph self.layout
.graph
.edge_weight( .edge_weight(
self.graph self.layout
.graph
.find_edge_undirected(self.index.node_index(), *ni) .find_edge_undirected(self.index.node_index(), *ni)
.unwrap() .unwrap()
.0, .0,
@ -262,19 +318,27 @@ impl<'a> LooseDot<'a> {
Label::Adjacent 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)) .map(|ni| LooseSegIndex::new(ni))
.next() .next()
} }
pub fn bend(&self) -> LooseBendIndex { pub fn bend(&self) -> LooseBendIndex {
self.graph self.layout
.graph
.neighbors_undirected(self.index.node_index()) .neighbors_undirected(self.index.node_index())
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.graph self.layout
.graph
.edge_weight( .edge_weight(
self.graph self.layout
.graph
.find_edge_undirected(self.index.node_index(), *ni) .find_edge_undirected(self.index.node_index(), *ni)
.unwrap() .unwrap()
.0, .0,
@ -283,7 +347,12 @@ impl<'a> LooseDot<'a> {
Label::Adjacent 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)) .map(|ni| LooseBendIndex::new(ni))
.next() .next()
.unwrap() .unwrap()
@ -299,7 +368,7 @@ impl<'a> MakeShape for LooseDot<'a> {
} }
pub type FixedSeg<'a> = GenericPrimitive<'a, FixedSegWeight>; pub type FixedSeg<'a> = GenericPrimitive<'a, FixedSegWeight>;
impl_primitive!(FixedSeg, FixedSegWeight); impl_fixed_primitive!(FixedSeg, FixedSegWeight);
impl<'a> MakeShape for FixedSeg<'a> { impl<'a> MakeShape for FixedSeg<'a> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
@ -322,7 +391,7 @@ impl<'a> GetEnds<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {} impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {}
pub type LooseSeg<'a> = GenericPrimitive<'a, LooseSegWeight>; pub type LooseSeg<'a> = GenericPrimitive<'a, LooseSegWeight>;
impl_primitive!(LooseSeg, LooseSegWeight); impl_loose_primitive!(LooseSeg, LooseSegWeight);
impl<'a> MakeShape for LooseSeg<'a> { impl<'a> MakeShape for LooseSeg<'a> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
@ -347,9 +416,9 @@ impl<'a> GetWidth for LooseSeg<'a> {
impl<'a> GetEnds<DotIndex, LooseDotIndex> for LooseSeg<'a> { impl<'a> GetEnds<DotIndex, LooseDotIndex> for LooseSeg<'a> {
fn ends(&self) -> (DotIndex, LooseDotIndex) { fn ends(&self) -> (DotIndex, LooseDotIndex) {
let v = self.adjacents(); 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])) (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])) (FixedDotIndex::new(v[1]).into(), LooseDotIndex::new(v[0]))
} else { } else {
(LooseDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1])) (LooseDotIndex::new(v[0]).into(), LooseDotIndex::new(v[1]))
@ -360,7 +429,7 @@ impl<'a> GetEnds<DotIndex, LooseDotIndex> for LooseSeg<'a> {
impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> for LooseSeg<'a> {} impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> for LooseSeg<'a> {}
pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>; pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>;
impl_primitive!(FixedBend, FixedBendWeight); impl_fixed_primitive!(FixedBend, FixedBendWeight);
impl<'a> FixedBend<'a> { impl<'a> FixedBend<'a> {
fn inner_radius(&self) -> f64 { 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> {} //impl<'a> GetInnerOuter for FixedBend<'a> {}
pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>; pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>;
impl_primitive!(LooseBend, LooseBendWeight); impl_loose_primitive!(LooseBend, LooseBendWeight);
impl<'a> LooseBend<'a> { impl<'a> LooseBend<'a> {
fn inner_radius(&self) -> f64 { fn inner_radius(&self) -> f64 {

View File

@ -94,7 +94,7 @@ impl Router {
mesh.generate(&self.layout)?; mesh.generate(&self.layout)?;
let mut tracer = self.tracer(&mesh); let mut tracer = self.tracer(&mesh);
let trace = tracer.start(from); let trace = tracer.start(from, 3.0);
let (_cost, _path) = astar( let (_cost, _path) = astar(
&mesh, &mesh,

View File

@ -4,6 +4,7 @@ use crate::{
graph::{ graph::{
GetEnds, Index, Interior, Label, LooseBendIndex, LooseDotIndex, LooseSegIndex, Weight, GetEnds, Index, Interior, Label, LooseBendIndex, LooseDotIndex, LooseSegIndex, Weight,
}, },
layout::Layout,
primitive::{GetOtherEnd, LooseBend, LooseDot}, primitive::{GetOtherEnd, LooseBend, LooseDot},
}; };
@ -15,10 +16,10 @@ pub struct Segbend {
} }
impl Segbend { impl Segbend {
pub fn from_dot(dot: LooseDotIndex, graph: &StableDiGraph<Weight, Label, usize>) -> Self { pub fn from_dot(dot: LooseDotIndex, layout: &Layout) -> Self {
let bend = LooseDot::new(dot, graph).bend(); let bend = LooseDot::new(dot, layout).bend();
let dot = LooseBend::new(bend, graph).other_end(dot); let dot = LooseBend::new(bend, layout).other_end(dot);
let seg = LooseDot::new(dot, graph).seg().unwrap(); let seg = LooseDot::new(dot, layout).seg().unwrap();
Self { bend, dot, seg } Self { bend, dot, seg }
} }
} }

View File

@ -2,8 +2,8 @@ use contracts::debug_ensures;
use crate::{ use crate::{
draw::{BareHead, Draw, Head, SegbendHead}, draw::{BareHead, Draw, Head, SegbendHead},
graph::{FixedDotIndex, LooseBendIndex}, graph::{FixedDotIndex, GetNet, LooseBendIndex},
layout::Layout, layout::{Band, Layout},
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
primitive::{GetFirstRail, GetInnerOuter}, primitive::{GetFirstRail, GetInnerOuter},
rules::Rules, 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 { Trace {
path: vec![from.into()], path: vec![from.into()],
head: BareHead { dot: from }.into(), head: BareHead { dot: from, band }.into(),
} }
} }

View File

@ -2,20 +2,18 @@ use petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
graph::{Label, LooseBendIndex, Weight}, graph::{Label, LooseBendIndex, Weight},
layout::Layout,
primitive::{GenericPrimitive, GetInnerOuter}, primitive::{GenericPrimitive, GetInnerOuter},
}; };
pub struct OutwardRailTraverser<'a> { pub struct OutwardRailTraverser<'a> {
rail: Option<LooseBendIndex>, rail: Option<LooseBendIndex>,
graph: &'a StableDiGraph<Weight, Label, usize>, layout: &'a Layout,
} }
impl<'a> OutwardRailTraverser<'a> { impl<'a> OutwardRailTraverser<'a> {
pub fn new( pub fn new(rail: Option<LooseBendIndex>, layout: &'a Layout) -> Self {
rail: Option<LooseBendIndex>, Self { rail, layout }
graph: &'a StableDiGraph<Weight, Label, usize>,
) -> Self {
Self { rail, graph }
} }
} }
@ -24,7 +22,7 @@ impl<'a> Iterator for OutwardRailTraverser<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.rail.map(|rail| { self.rail.map(|rail| {
self.rail = GenericPrimitive::new(rail, self.graph).outer(); self.rail = GenericPrimitive::new(rail, self.layout).outer();
rail rail
}) })
} }