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]
version = "0.6.3"
[dependencies.slab]
version = "0.4.9"
[dependencies.spade]
version = "2.2.0"

View File

@ -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<SegbendHead, ()> {
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 {

View File

@ -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<Weight, Label, usize>,
) -> 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<BendIndex> for Index {
}
}
pub trait DotWeight: GetNet + GetWidth + Into<Weight> + Copy {}
pub trait DotWeight: GetWidth + Into<Weight> + 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<Weight> + Copy {}
pub trait SegWeight: Into<Weight> + 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<Weight> + Copy {}
pub trait BendWeight: Into<Weight> + 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<Weight, Label, usize>) -> Primitive<'a>;
fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>;
}
#[derive(Debug, Clone, Copy)]

View File

@ -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,

View File

@ -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<Shape, Index>;
#[derive(Debug)]
pub struct Band {
pub net: i64,
pub width: f64,
}
#[derive(Debug)]
pub struct Layout {
rtree: RTree<RTreeWrapper>,
pub bands: Slab<Band>,
pub graph: StableDiGraph<Weight, Label, usize>,
}
@ -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<Item = Shape> + '_ {
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<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> {
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

View File

@ -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)

View File

@ -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) => {

View File

@ -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<Weight, Label, usize>;
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<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
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<LooseBendIndex> {
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<LooseBendIndex> {
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<LooseBendIndex> {
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<W>,
graph: &'a StableDiGraph<Weight, Label, usize>,
layout: &'a Layout,
}
impl<'a, W> GenericPrimitive<'a, W> {
pub fn new(index: GenericIndex<W>, graph: &'a StableDiGraph<Weight, Label, usize>) -> Self {
Self { index, graph }
pub fn new(index: GenericIndex<W>, 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<NodeIndex<usize>> {
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<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> {
fn graph(&self) -> &StableDiGraph<Weight, Label, usize> {
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<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> 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<LooseSegIndex> {
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<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {
impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> 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<DotIndex, LooseDotIndex> 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<DotIndex, LooseDotIndex> for LooseSeg<'a> {
impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> 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 {

View File

@ -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,

View File

@ -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<Weight, Label, usize>) -> 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 }
}
}

View File

@ -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(),
}
}

View File

@ -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<LooseBendIndex>,
graph: &'a StableDiGraph<Weight, Label, usize>,
layout: &'a Layout,
}
impl<'a> OutwardRailTraverser<'a> {
pub fn new(
rail: Option<LooseBendIndex>,
graph: &'a StableDiGraph<Weight, Label, usize>,
) -> Self {
Self { rail, graph }
pub fn new(rail: Option<LooseBendIndex>, layout: &'a Layout) -> Self {
Self { rail, layout }
}
}
@ -24,7 +22,7 @@ impl<'a> Iterator for OutwardRailTraverser<'a> {
fn next(&mut self) -> Option<Self::Item> {
self.rail.map(|rail| {
self.rail = GenericPrimitive::new(rail, self.graph).outer();
self.rail = GenericPrimitive::new(rail, self.layout).outer();
rail
})
}