mirror of https://codeberg.org/topola/topola.git
graph,layout,primitive: store band index instead of net in loose weights
This commit is contained in:
parent
b8f6b32341
commit
294e6c4f72
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
60
src/draw.rs
60
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<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 {
|
||||
|
|
|
|||
63
src/graph.rs
63
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<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)]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
199
src/primitive.rs
199
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<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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue