layout: move connectivity to new superordinate `Board` struct

This is very rudimentary (merely compiles and doesn't panic). Routing is
unlikely to work at the moment. I'll be fixing all this in subsequent
commits.
This commit is contained in:
Mikolaj Wielgus 2024-02-28 09:03:18 +00:00
parent b53dc62df3
commit 8d55fbc837
16 changed files with 124 additions and 455 deletions

View File

@ -12,10 +12,11 @@ macro_rules! dbg_dot {
use geo::point; use geo::point;
use painter::Painter; use painter::Painter;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use topola::board::connectivity::BandIndex;
use topola::board::Board;
use topola::draw::DrawException; use topola::draw::DrawException;
use topola::dsn::design::DsnDesign; use topola::dsn::design::DsnDesign;
use topola::geometry::shape::{Shape, ShapeTrait}; use topola::geometry::shape::{Shape, ShapeTrait};
use topola::layout::connectivity::BandIndex;
use topola::layout::dot::FixedDotWeight; use topola::layout::dot::FixedDotWeight;
use topola::layout::graph::{GeometryIndex, MakePrimitive}; use topola::layout::graph::{GeometryIndex, MakePrimitive};
use topola::layout::primitive::MakeShape; use topola::layout::primitive::MakeShape;
@ -126,7 +127,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.window, self.window,
self.renderer, self.renderer,
self.font_context, self.font_context,
RouterOrLayout::Layout(tracer.layout), RouterOrLayout::Layout(&tracer.board.layout),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
@ -144,7 +145,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.window, self.window,
self.renderer, self.renderer,
self.font_context, self.font_context,
RouterOrLayout::Layout(tracer.layout), RouterOrLayout::Layout(&tracer.board.layout),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&path, &path,
@ -175,7 +176,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.window, self.window,
self.renderer, self.renderer,
self.font_context, self.font_context,
RouterOrLayout::Layout(tracer.layout), RouterOrLayout::Layout(&tracer.board.layout),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
@ -248,14 +249,15 @@ fn main() -> Result<(), anyhow::Error> {
let design = DsnDesign::load_from_file("tests/data/test.dsn")?; let design = DsnDesign::load_from_file("tests/data/test.dsn")?;
//dbg!(&design); //dbg!(&design);
let layout = design.make_layout(); let layout = design.make_layout();
let mut router = Router::new(layout); let board = Board::new(layout);
let mut router = Router::new(board);
render_times( render_times(
&mut event_pump, &mut event_pump,
&window, &window,
&mut renderer, &mut renderer,
&font_context, &font_context,
RouterOrLayout::Layout(&router.layout), RouterOrLayout::Layout(&router.board.layout),
None, None,
None, None,
&[], &[],
@ -278,7 +280,7 @@ fn main() -> Result<(), anyhow::Error> {
&window, &window,
&mut renderer, &mut renderer,
&font_context, &font_context,
RouterOrLayout::Layout(&router.layout), RouterOrLayout::Layout(&router.board.layout),
None, None,
None, None,
&[], &[],
@ -345,7 +347,7 @@ fn render_times(
maybe_mesh = None; maybe_mesh = None;
} }
&router.layout &router.board.layout
} }
RouterOrLayout::Layout(layout) => layout, RouterOrLayout::Layout(layout) => layout,
}; };

View File

@ -7,7 +7,7 @@ use crate::{
layout::{ layout::{
bend::{BendIndex, LooseBendWeight}, bend::{BendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight},
graph::{GetBandIndex, MakePrimitive}, graph::{GetNet, MakePrimitive},
guide::{Guide, Head, HeadTrait, SegbendHead}, guide::{Guide, Head, HeadTrait, SegbendHead},
primitive::GetOtherJoint, primitive::GetOtherJoint,
rules::RulesTrait, rules::RulesTrait,
@ -58,30 +58,17 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
let head = self let head = self
.extend_head(head, tangent.start_point()) .extend_head(head, tangent.start_point())
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
let net = head.face().primitive(self.layout).net();
match head.face() { match head.face() {
DotIndex::Fixed(dot) => { DotIndex::Fixed(dot) => {
self.layout self.layout
.add_lone_loose_seg( .add_lone_loose_seg(dot, into.into(), LoneLooseSegWeight { net, width })
dot,
into.into(),
LoneLooseSegWeight {
band: head.band(),
width: self.layout.band(head.band()).width(),
},
)
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
} }
DotIndex::Loose(dot) => { DotIndex::Loose(dot) => {
self.layout self.layout
.add_seq_loose_seg( .add_seq_loose_seg(into.into(), dot, SeqLooseSegWeight { net, width })
into.into(),
dot,
SeqLooseSegWeight {
band: head.band(),
width: self.layout.band(head.band()).width(),
},
)
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
} }
} }
@ -215,31 +202,24 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
width: f64, width: f64,
offset: f64, offset: f64,
) -> Result<SegbendHead, LayoutException> { ) -> Result<SegbendHead, LayoutException> {
let net = head.face().primitive(self.layout).net();
let segbend = self.layout.insert_segbend( let segbend = self.layout.insert_segbend(
head.face(), head.face(),
around, around,
LooseDotWeight { LooseDotWeight {
band: head.band(), net,
circle: Circle { circle: Circle {
pos: to, pos: to,
r: width / 2.0, r: width / 2.0,
}, },
}, },
SeqLooseSegWeight { SeqLooseSegWeight { net, width },
band: head.band(), LooseBendWeight { net, width, offset },
width,
},
LooseBendWeight {
band: head.band(),
width,
offset,
},
cw, cw,
)?; )?;
Ok::<SegbendHead, LayoutException>(SegbendHead { Ok::<SegbendHead, LayoutException>(SegbendHead {
face: self.layout.primitive(segbend.bend).other_joint(segbend.dot), face: self.layout.primitive(segbend.bend).other_joint(segbend.dot),
segbend, segbend,
band: head.band(),
}) })
} }
@ -250,10 +230,9 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
.layout .layout
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_joint(head.segbend.dot.into()); .other_joint(head.segbend.dot.into());
let band = head.band;
self.layout.remove_segbend(&head.segbend, head.face); self.layout.remove_segbend(&head.segbend, head.face);
Some(self.guide().head(prev_dot, band)) Some(self.guide().head(prev_dot))
} }
fn guide(&self) -> Guide<R> { fn guide(&self) -> Guide<R> {

View File

@ -7,8 +7,8 @@ use crate::{
use super::{ use super::{
de::{from_str, Error}, de::{from_str, Error},
structure::Pcb,
rules::Rules, rules::Rules,
structure::Pcb,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -24,10 +24,7 @@ impl DsnDesign {
let rules = Rules::from_pcb(&pcb); let rules = Rules::from_pcb(&pcb);
Ok(Self { Ok(Self { pcb, rules })
pcb,
rules,
})
} }
pub fn make_layout(&self) -> Layout<&Rules> { pub fn make_layout(&self) -> Layout<&Rules> {
@ -67,7 +64,6 @@ impl DsnDesign {
for pin in &image.pins { for pin in &image.pins {
let pin_name = format!("{}-{}", place.name, pin.id); let pin_name = format!("{}-{}", place.name, pin.id);
let net_id = pin_nets.get(&pin_name).unwrap(); let net_id = pin_nets.get(&pin_name).unwrap();
let continent = layout.add_continent(*net_id);
let padstack = &self let padstack = &self
.pcb .pcb
@ -85,7 +81,10 @@ impl DsnDesign {
}; };
layout layout
.add_fixed_dot(FixedDotWeight { continent, circle }) .add_fixed_dot(FixedDotWeight {
net: *net_id as i64,
circle,
})
.unwrap(); .unwrap();
} }
} }
@ -100,7 +99,6 @@ impl DsnDesign {
.iter() .iter()
.map(|via| { .map(|via| {
let net_id = self.rules.net_ids.get(&via.net.0).unwrap(); let net_id = self.rules.net_ids.get(&via.net.0).unwrap();
let continent = layout.add_continent(*net_id);
// find the padstack referenced by this via placement // find the padstack referenced by this via placement
let padstack = &self let padstack = &self
@ -119,19 +117,21 @@ impl DsnDesign {
}; };
layout layout
.add_fixed_dot(FixedDotWeight { continent, circle }) .add_fixed_dot(FixedDotWeight {
net: *net_id as i64,
circle,
})
.unwrap() .unwrap()
}) })
.collect(); .collect();
for wire in self.pcb.wiring.wires.iter() { for wire in self.pcb.wiring.wires.iter() {
let net_id = self.rules.net_ids.get(&wire.net.0).unwrap(); let net_id = self.rules.net_ids.get(&wire.net.0).unwrap();
let continent = layout.add_continent(*net_id);
// add the first coordinate in the wire path as a dot and save its index // add the first coordinate in the wire path as a dot and save its index
let mut prev_index = layout let mut prev_index = layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
continent, net: *net_id as i64,
circle: Circle { circle: Circle {
pos: ( pos: (
wire.path.coords[0].x as f64 / 100.0, wire.path.coords[0].x as f64 / 100.0,
@ -147,7 +147,7 @@ impl DsnDesign {
for coord in wire.path.coords.iter().skip(1) { for coord in wire.path.coords.iter().skip(1) {
let index = layout let index = layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
continent, net: *net_id as i64,
circle: Circle { circle: Circle {
pos: (coord.x as f64 / 100.0, -coord.y as f64 / 100.0).into(), pos: (coord.x as f64 / 100.0, -coord.y as f64 / 100.0).into(),
r: wire.path.width as f64 / 100.0, r: wire.path.width as f64 / 100.0,
@ -161,7 +161,7 @@ impl DsnDesign {
prev_index, prev_index,
index, index,
FixedSegWeight { FixedSegWeight {
continent, net: *net_id as i64,
width: wire.path.width as f64 / 100.0, width: wire.path.width as f64 / 100.0,
}, },
) )

View File

@ -1,100 +0,0 @@
use crate::{
geometry::{shape::ShapeTrait, GetWidth},
graph::GetNodeIndex,
layout::{
connectivity::{BandIndex, BandWeight, ConnectivityWeight, GetNet},
dot::{DotIndex, FixedDotIndex},
graph::{GeometryIndex, MakePrimitive},
loose::{GetNextLoose, LooseIndex},
primitive::{GetJoints, GetOtherJoint, MakeShape},
Layout,
},
};
use super::rules::RulesTrait;
pub struct Band<'a, R: RulesTrait> {
pub index: BandIndex,
layout: &'a Layout<R>,
}
impl<'a, R: RulesTrait> Band<'a, R> {
pub fn new(index: BandIndex, layout: &'a Layout<R>) -> Self {
Self { index, layout }
}
fn weight(&self) -> BandWeight {
if let Some(ConnectivityWeight::Band(weight)) = self
.layout
.connectivity()
.node_weight(self.index.node_index())
{
*weight
} else {
unreachable!()
}
}
pub fn from(&self) -> FixedDotIndex {
self.weight().from
}
pub fn to(&self) -> Option<FixedDotIndex> {
// For now, we do full traversal. Later on, we may want to store the target fixed dot
// somewhere.
let mut maybe_loose = self.layout.primitive(self.from()).first_loose(self.index);
let mut prev = None;
while let Some(loose) = maybe_loose {
let prev_prev = prev;
prev = maybe_loose;
maybe_loose = self.layout.loose(loose).next_loose(prev_prev);
}
match prev {
Some(LooseIndex::LoneSeg(seg)) => {
Some(self.layout.primitive(seg).other_joint(self.from()))
}
Some(LooseIndex::SeqSeg(seg)) => {
if let DotIndex::Fixed(dot) = self.layout.primitive(seg).joints().0 {
Some(dot)
} else {
None
}
}
_ => unreachable!(),
}
}
pub fn length(&self) -> f64 {
let mut maybe_loose = self.layout.primitive(self.from()).first_loose(self.index);
let mut prev = None;
let mut length = 0.0;
while let Some(loose) = maybe_loose {
length += GeometryIndex::from(loose)
.primitive(self.layout)
.shape()
.length();
let prev_prev = prev;
prev = maybe_loose;
maybe_loose = self.layout.loose(loose).next_loose(prev_prev);
}
length
}
}
impl<'a, R: RulesTrait> GetNet for Band<'a, R> {
fn net(&self) -> i64 {
self.weight().net
}
}
impl<'a, R: RulesTrait> GetWidth for Band<'a, R> {
fn width(&self) -> f64 {
self.weight().width
}
}

View File

@ -4,11 +4,7 @@ use crate::{
geometry::{BendWeightTrait, GetOffset, GetWidth, SetOffset}, geometry::{BendWeightTrait, GetOffset, GetWidth, SetOffset},
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::{ layout::{
connectivity::{BandIndex, ContinentIndex}, graph::{GeometryIndex, GeometryWeight, GetNet, MakePrimitive, Retag},
graph::{
GeometryIndex, GeometryWeight, GetBandIndex, GetContinentIndex, GetContinentIndexMut,
MakePrimitive, Retag,
},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Layout,
@ -77,7 +73,7 @@ impl BendWeightTrait<GeometryWeight> for BendWeight {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedBendWeight { pub struct FixedBendWeight {
pub continent: ContinentIndex, pub net: i64,
pub width: f64, pub width: f64,
pub offset: f64, pub offset: f64,
} }
@ -105,7 +101,7 @@ impl GetWidth for FixedBendWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LooseBendWeight { pub struct LooseBendWeight {
pub band: BandIndex, pub net: i64,
pub width: f64, pub width: f64,
pub offset: f64, pub offset: f64,
} }

View File

@ -1,51 +0,0 @@
use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::StableDiGraph;
use crate::{graph::GenericIndex, layout::dot::FixedDotIndex};
#[enum_dispatch]
pub trait GetNet {
fn net(&self) -> i64;
}
pub type ConnectivityGraph = StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>;
#[enum_dispatch(GetNet)]
#[derive(Debug, Clone, Copy)]
pub enum ConnectivityWeight {
Continent(ContinentWeight),
Band(BandWeight),
}
#[derive(Debug, Clone, Copy)]
pub struct ContinentWeight {
pub net: i64,
}
impl GetNet for ContinentWeight {
fn net(&self) -> i64 {
self.net
}
}
pub type ContinentIndex = GenericIndex<ContinentWeight>;
#[derive(Debug, Clone, Copy)]
pub struct BandWeight {
pub net: i64,
pub width: f64,
pub from: FixedDotIndex,
}
impl GetNet for BandWeight {
fn net(&self) -> i64 {
self.net
}
}
pub type BandIndex = GenericIndex<BandWeight>;
#[derive(Debug, Clone, Copy)]
pub enum ConnectivityLabel {
Band,
}

View File

@ -7,11 +7,7 @@ use crate::{
geometry::{DotWeightTrait, GetPos, GetWidth, SetPos}, geometry::{DotWeightTrait, GetPos, GetWidth, SetPos},
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::{ layout::{
connectivity::{BandIndex, ContinentIndex}, graph::{GeometryIndex, GeometryWeight, GetNet, MakePrimitive, Retag},
graph::{
GeometryIndex, GeometryWeight, GetBandIndex, GetContinentIndex, GetContinentIndexMut,
MakePrimitive, Retag,
},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Layout,
@ -79,7 +75,7 @@ impl DotWeightTrait<GeometryWeight> for DotWeight {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedDotWeight { pub struct FixedDotWeight {
pub continent: ContinentIndex, pub net: i64,
pub circle: Circle, pub circle: Circle,
} }
@ -106,7 +102,7 @@ impl GetWidth for FixedDotWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LooseDotWeight { pub struct LooseDotWeight {
pub band: BandIndex, pub net: i64,
pub circle: Circle, pub circle: Circle,
} }

View File

@ -3,11 +3,9 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
board::connectivity::{BandIndex, ContinentIndex},
graph::GetNodeIndex, graph::GetNodeIndex,
layout::{ layout::Layout,
connectivity::{BandIndex, ContinentIndex},
Layout,
},
}; };
use super::{ use super::{
@ -27,16 +25,8 @@ pub trait Retag<GeometryIndex> {
} }
#[enum_dispatch] #[enum_dispatch]
pub trait GetContinentIndex { pub trait GetNet {
fn continent(&self) -> ContinentIndex; fn net(&self) -> i64;
}
pub trait GetContinentIndexMut {
fn continent_mut(&mut self) -> &mut ContinentIndex;
}
pub trait GetBandIndex {
fn band(&self) -> BandIndex;
} }
#[enum_dispatch] #[enum_dispatch]
@ -52,6 +42,12 @@ macro_rules! impl_weight {
} }
} }
impl<'a> GetNet for $weight_struct {
fn net(&self) -> i64 {
self.net
}
}
pub type $index_struct = GenericIndex<$weight_struct>; pub type $index_struct = GenericIndex<$weight_struct>;
impl MakePrimitive for $index_struct { impl MakePrimitive for $index_struct {
@ -65,30 +61,12 @@ macro_rules! impl_weight {
macro_rules! impl_fixed_weight { macro_rules! impl_fixed_weight {
($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => {
impl_weight!($weight_struct, $weight_variant, $index_struct); impl_weight!($weight_struct, $weight_variant, $index_struct);
impl GetContinentIndex for $weight_struct {
fn continent(&self) -> ContinentIndex {
self.continent
}
}
impl GetContinentIndexMut for $weight_struct {
fn continent_mut(&mut self) -> &mut ContinentIndex {
&mut self.continent
}
}
}; };
} }
macro_rules! impl_loose_weight { macro_rules! impl_loose_weight {
($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => { ($weight_struct:ident, $weight_variant:ident, $index_struct:ident) => {
impl_weight!($weight_struct, $weight_variant, $index_struct); impl_weight!($weight_struct, $weight_variant, $index_struct);
impl GetBandIndex for $weight_struct {
fn band(&self) -> BandIndex {
self.band
}
}
}; };
} }

View File

@ -2,12 +2,12 @@ use enum_dispatch::enum_dispatch;
use geo::Line; use geo::Line;
use crate::{ use crate::{
board::connectivity::BandIndex,
geometry::shape::{Shape, ShapeTrait}, geometry::shape::{Shape, ShapeTrait},
layout::{ layout::{
bend::BendIndex, bend::BendIndex,
connectivity::BandIndex,
dot::{DotIndex, FixedDotIndex, LooseDotIndex}, dot::{DotIndex, FixedDotIndex, LooseDotIndex},
graph::{GetBandIndex, MakePrimitive}, graph::MakePrimitive,
primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape},
rules::GetConditions, rules::GetConditions,
Layout, Layout,
@ -25,7 +25,6 @@ use super::{
#[enum_dispatch] #[enum_dispatch]
pub trait HeadTrait { pub trait HeadTrait {
fn face(&self) -> DotIndex; fn face(&self) -> DotIndex;
fn band(&self) -> BandIndex;
} }
#[enum_dispatch(HeadTrait)] #[enum_dispatch(HeadTrait)]
@ -38,34 +37,24 @@ 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: BandIndex,
} }
impl HeadTrait for BareHead { impl HeadTrait for BareHead {
fn face(&self) -> DotIndex { fn face(&self) -> DotIndex {
self.dot.into() self.dot.into()
} }
fn band(&self) -> BandIndex {
self.band
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct SegbendHead { pub struct SegbendHead {
pub face: LooseDotIndex, pub face: LooseDotIndex,
pub segbend: Segbend, pub segbend: Segbend,
pub band: BandIndex,
} }
impl HeadTrait for SegbendHead { impl HeadTrait for SegbendHead {
fn face(&self) -> DotIndex { fn face(&self) -> DotIndex {
self.face.into() self.face.into()
} }
fn band(&self) -> BandIndex {
self.band
}
} }
pub struct Guide<'a, R: RulesTrait> { pub struct Guide<'a, R: RulesTrait> {
@ -233,20 +222,16 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
SegbendHead { SegbendHead {
face: dot, face: dot,
segbend: self.layout.segbend(dot), segbend: self.layout.segbend(dot),
band: self.layout.primitive(dot).weight().band(),
} }
} }
pub fn rear_head(&self, dot: LooseDotIndex) -> Head { pub fn rear_head(&self, dot: LooseDotIndex) -> Head {
self.head( self.head(self.rear(self.segbend_head(dot)))
self.rear(self.segbend_head(dot)),
self.layout.primitive(dot).weight().band(),
)
} }
pub fn head(&self, dot: DotIndex, band: BandIndex) -> Head { pub fn head(&self, dot: DotIndex) -> Head {
match dot { match dot {
DotIndex::Fixed(fixed) => BareHead { dot: fixed, band }.into(), DotIndex::Fixed(fixed) => BareHead { dot: fixed }.into(),
DotIndex::Loose(loose) => self.segbend_head(loose).into(), DotIndex::Loose(loose) => self.segbend_head(loose).into(),
} }
} }

View File

@ -1,16 +1,10 @@
use contracts::debug_ensures; use contracts::debug_ensures;
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use geo::Point; use geo::Point;
use petgraph::stable_graph::StableDiGraph;
use rstar::RTreeObject; use rstar::RTreeObject;
use thiserror::Error; use thiserror::Error;
use super::band::Band;
use super::connectivity::{
BandIndex, BandWeight, ConnectivityGraph, ConnectivityLabel, ConnectivityWeight,
ContinentIndex, ContinentWeight, GetNet,
};
use super::loose::{GetNextLoose, Loose, LooseIndex}; use super::loose::{GetNextLoose, Loose, LooseIndex};
use super::rules::RulesTrait; use super::rules::RulesTrait;
use super::segbend::Segbend; use super::segbend::Segbend;
@ -24,13 +18,14 @@ use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::bend::BendIndex; use crate::layout::bend::BendIndex;
use crate::layout::collect::Collect; use crate::layout::collect::Collect;
use crate::layout::dot::DotWeight; use crate::layout::dot::DotWeight;
use crate::layout::graph::GetNet;
use crate::layout::guide::Guide; use crate::layout::guide::Guide;
use crate::layout::primitive::GetLimbs; use crate::layout::primitive::GetLimbs;
use crate::layout::rules::GetConditions; use crate::layout::rules::GetConditions;
use crate::layout::{ use crate::layout::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
graph::{GeometryIndex, GeometryWeight, GetContinentIndex, MakePrimitive}, graph::{GeometryIndex, GeometryWeight, MakePrimitive},
primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape}, primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape},
seg::{ seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
@ -81,7 +76,6 @@ pub struct Layout<R: RulesTrait> {
SegIndex, SegIndex,
BendIndex, BendIndex,
>, >,
connectivity: ConnectivityGraph,
rules: R, rules: R,
} }
@ -89,19 +83,17 @@ impl<R: RulesTrait> Layout<R> {
pub fn new(rules: R) -> Self { pub fn new(rules: R) -> Self {
Self { Self {
geometry_with_rtree: GeometryWithRtree::new(), geometry_with_rtree: GeometryWithRtree::new(),
connectivity: StableDiGraph::default(),
rules, rules,
} }
} }
pub fn remove_band(&mut self, band: BandIndex) { pub fn remove_band(&mut self, first_loose: SeqLooseSegIndex) {
let mut dots = vec![]; let mut dots = vec![];
let mut segs = vec![]; let mut segs = vec![];
let mut bends = vec![]; let mut bends = vec![];
let mut outers = vec![]; let mut outers = vec![];
let from = self.band(band).from(); let mut maybe_loose = Some(first_loose.into());
let mut maybe_loose = self.primitive(from).first_loose(band);
let mut prev = None; let mut prev = None;
while let Some(loose) = maybe_loose { while let Some(loose) = maybe_loose {
@ -149,8 +141,6 @@ impl<R: RulesTrait> Layout<R> {
for outer in outers { for outer in outers {
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail. self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
} }
self.connectivity.remove_node(band.node_index());
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 4))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 4))]
@ -176,30 +166,6 @@ impl<R: RulesTrait> Layout<R> {
} }
} }
// TODO: This method shouldn't be public.
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_continent(&mut self, net: i64) -> ContinentIndex {
ContinentIndex::new(
self.connectivity
.add_node(ConnectivityWeight::Continent(ContinentWeight { net })),
)
}
// TODO: This method shouldn't be public.
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_band(&mut self, from: FixedDotIndex, width: f64) -> BandIndex {
BandIndex::new(
self.connectivity
.add_node(ConnectivityWeight::Band(BandWeight {
width,
net: self.primitive(from).net(),
from,
})),
)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
@ -489,18 +455,6 @@ impl<R: RulesTrait> Layout<R> {
weight: LoneLooseSegWeight, weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> { ) -> Result<LoneLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from.into(), to.into(), weight, &[])?; let seg = self.add_seg_infringably(from.into(), to.into(), weight, &[])?;
self.connectivity.update_edge(
self.primitive(from).continent().node_index(),
weight.band.node_index(),
ConnectivityLabel::Band,
);
self.connectivity.update_edge(
weight.band.node_index(),
self.primitive(to).continent().node_index(),
ConnectivityLabel::Band,
);
Ok(seg) Ok(seg)
} }
@ -515,15 +469,6 @@ impl<R: RulesTrait> Layout<R> {
weight: SeqLooseSegWeight, weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> { ) -> Result<SeqLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from, to.into(), weight, &[])?; let seg = self.add_seg_infringably(from, to.into(), weight, &[])?;
if let DotIndex::Fixed(dot) = from {
self.connectivity.update_edge(
self.primitive(dot).continent().node_index(),
weight.band.node_index(),
ConnectivityLabel::Band,
);
}
Ok(seg) Ok(seg)
} }
@ -547,22 +492,6 @@ impl<R: RulesTrait> Layout<R> {
Ok(seg) Ok(seg)
} }
/*#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
pub fn add_fixed_bend(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
around: GeometryIndex,
weight: FixedBendWeight,
) -> Result<FixedBendIndex, ()> {
match around {
GeometryIndex::FixedDot(core) => self.add_core_bend(from, to, core, weight),
GeometryIndex::FixedBend(around) => self.add_outer_bend(from, to, around, weight),
_ => unreachable!(),
}
}*/
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3) #[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3)
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))] || self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))]
@ -577,15 +506,14 @@ impl<R: RulesTrait> Layout<R> {
infringables: &[GeometryIndex], infringables: &[GeometryIndex],
) -> Result<LooseBendIndex, LayoutException> { ) -> Result<LooseBendIndex, LayoutException> {
// It makes no sense to wrap something around or under one of its connectables. // It makes no sense to wrap something around or under one of its connectables.
let net = self.band(weight.band).net();
// //
if net == around.primitive(self).net() { if weight.net == around.primitive(self).net() {
return Err(AlreadyConnected(net, around.into()).into()); return Err(AlreadyConnected(weight.net, around.into()).into());
} }
// //
if let Some(wraparound) = self.wraparoundable(around).wraparound() { if let Some(wraparound) = self.wraparoundable(around).wraparound() {
if net == wraparound.primitive(self).net() { if weight.net == wraparound.primitive(self).net() {
return Err(AlreadyConnected(net, wraparound.into()).into()); return Err(AlreadyConnected(weight.net, wraparound.into()).into());
} }
} }
@ -847,12 +775,6 @@ impl<R: RulesTrait> Layout<R> {
} }
impl<R: RulesTrait> Layout<R> { impl<R: RulesTrait> Layout<R> {
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn connectivity(&self) -> &ConnectivityGraph {
&self.connectivity
}
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn geometry( pub fn geometry(
@ -905,10 +827,4 @@ impl<R: RulesTrait> Layout<R> {
pub fn loose(&self, index: LooseIndex) -> Loose<R> { pub fn loose(&self, index: LooseIndex) -> Loose<R> {
Loose::new(index, self) Loose::new(index, self)
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn band(&self, index: BandIndex) -> Band<R> {
Band::new(index, self)
}
} }

View File

@ -1,9 +1,7 @@
#[macro_use] #[macro_use]
pub mod graph; pub mod graph;
pub mod band;
pub mod bend; pub mod bend;
pub mod collect; pub mod collect;
pub mod connectivity;
pub mod dot; pub mod dot;
pub mod guide; pub mod guide;
mod layout; mod layout;

View File

@ -1,26 +1,26 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::board::connectivity::{BandIndex, ContinentIndex};
use crate::geometry::{ use crate::geometry::{
shape::{Shape, ShapeTrait}, shape::{Shape, ShapeTrait},
GetOffset, GetWidth, GetOffset, GetWidth,
}; };
use crate::graph::{GenericIndex, GetNodeIndex}; use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::dot::DotWeight;
use crate::layout::seg::{
FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex,
SeqLooseSegWeight,
};
use crate::layout::{ use crate::layout::{
bend::{BendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, bend::{BendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
connectivity::{BandIndex, ContinentIndex, GetNet}, dot::DotWeight,
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
graph::{GeometryIndex, GeometryWeight, GetBandIndex, GetContinentIndex, Retag}, graph::{GeometryIndex, GeometryWeight, Retag},
loose::LooseIndex, loose::LooseIndex,
seg::{
FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex,
SeqLooseSegWeight,
},
Layout, Layout,
}; };
use super::graph::GetNet;
use super::rules::{Conditions, GetConditions, RulesTrait}; use super::rules::{Conditions, GetConditions, RulesTrait};
#[enum_dispatch] #[enum_dispatch]
@ -126,44 +126,24 @@ macro_rules! impl_primitive {
} }
} }
} }
impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 {
self.weight().net()
}
}
}; };
} }
macro_rules! impl_fixed_primitive { macro_rules! impl_fixed_primitive {
($primitive_struct:ident, $weight_struct:ident) => { ($primitive_struct:ident, $weight_struct:ident) => {
impl_primitive!($primitive_struct, $weight_struct); impl_primitive!($primitive_struct, $weight_struct);
impl<'a, R: RulesTrait> GetContinentIndex for $primitive_struct<'a, R> {
fn continent(&self) -> ContinentIndex {
self.weight().continent()
}
}
impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 {
self.layout()
.connectivity()
.node_weight(self.continent().node_index())
.unwrap()
.net()
}
}
}; };
} }
macro_rules! impl_loose_primitive { macro_rules! impl_loose_primitive {
($primitive_struct:ident, $weight_struct:ident) => { ($primitive_struct:ident, $weight_struct:ident) => {
impl_primitive!($primitive_struct, $weight_struct); impl_primitive!($primitive_struct, $weight_struct);
impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 {
self.layout()
.connectivity()
.node_weight(self.weight().band().node_index())
.unwrap()
.net()
}
}
}; };
} }

View File

@ -4,11 +4,7 @@ use crate::{
geometry::{GetWidth, SegWeightTrait}, geometry::{GetWidth, SegWeightTrait},
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::{ layout::{
connectivity::{BandIndex, ContinentIndex}, graph::{GeometryIndex, GeometryWeight, GetNet, MakePrimitive, Retag},
graph::{
GeometryIndex, GeometryWeight, GetBandIndex, GetContinentIndex, GetContinentIndexMut,
MakePrimitive, Retag,
},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Layout,
@ -83,7 +79,7 @@ impl SegWeightTrait<GeometryWeight> for SegWeight {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedSegWeight { pub struct FixedSegWeight {
pub continent: ContinentIndex, pub net: i64,
pub width: f64, pub width: f64,
} }
@ -98,7 +94,7 @@ impl GetWidth for FixedSegWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct LoneLooseSegWeight { pub struct LoneLooseSegWeight {
pub band: BandIndex, pub net: i64,
pub width: f64, pub width: f64,
} }
@ -113,7 +109,7 @@ impl GetWidth for LoneLooseSegWeight {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct SeqLooseSegWeight { pub struct SeqLooseSegWeight {
pub band: BandIndex, pub net: i64,
pub width: f64, pub width: f64,
} }

View File

@ -5,6 +5,7 @@ pub mod draw;
pub mod graph; pub mod graph;
#[macro_use] #[macro_use]
pub mod layout; pub mod layout;
pub mod board;
pub mod dsn; pub mod dsn;
pub mod geometry; pub mod geometry;
pub mod math; pub mod math;

View File

@ -5,16 +5,16 @@ use spade::InsertionError;
use thiserror::Error; use thiserror::Error;
use crate::astar::{astar, AstarStrategy, PathTracker}; use crate::astar::{astar, AstarStrategy, PathTracker};
use crate::board::connectivity::BandIndex;
use crate::board::Board;
use crate::draw::DrawException; use crate::draw::DrawException;
use crate::geometry::{shape::ShapeTrait, GetWidth}; use crate::geometry::{shape::ShapeTrait, GetWidth};
use crate::layout::guide::HeadTrait;
use crate::layout::rules::RulesTrait;
use crate::layout::Layout;
use crate::layout::{ use crate::layout::{
connectivity::BandIndex,
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::MakeShape, primitive::MakeShape,
rules::RulesTrait,
Layout,
}; };
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
@ -53,7 +53,7 @@ pub trait RouterObserverTrait<R: RulesTrait> {
} }
pub struct Router<R: RulesTrait> { pub struct Router<R: RulesTrait> {
pub layout: Layout<R>, pub board: Board<R>,
} }
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> { struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
@ -84,24 +84,14 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
{ {
fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool { fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool {
let new_path = tracker.reconstruct_path_to(vertex); let new_path = tracker.reconstruct_path_to(vertex);
let band = self.trace.head.band(); let width = self.trace.width;
self.tracer self.tracer
.rework_path( .rework_path(&mut self.trace, &new_path, width)
&mut self.trace,
&new_path,
self.tracer.layout.band(band).width(),
)
.unwrap(); .unwrap();
self.observer.on_rework(&self.tracer, &self.trace); self.observer.on_rework(&self.tracer, &self.trace);
self.tracer self.tracer.finish(&mut self.trace, self.to, width).is_ok()
.finish(
&mut self.trace,
self.to,
self.tracer.layout.band(band).width(),
)
.is_ok()
} }
fn edge_cost(&mut self, edge: MeshEdgeReference) -> Option<f64> { fn edge_cost(&mut self, edge: MeshEdgeReference) -> Option<f64> {
@ -110,18 +100,14 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
return None; return None;
} }
let band = self.trace.head.band(); let before_probe_length = self.tracer.board.band_length(self.trace.band);
let before_probe_length = self.tracer.layout.band(band).length();
let result = self.tracer.step( let width = self.trace.width;
&mut self.trace, let result = self.tracer.step(&mut self.trace, edge.target(), width);
edge.target(),
self.tracer.layout.band(band).width(),
);
self.observer self.observer
.on_probe(&self.tracer, &self.trace, edge, result); .on_probe(&self.tracer, &self.trace, edge, result);
let probe_length = self.tracer.layout.band(self.trace.head.band()).length(); let probe_length = self.tracer.board.band_length(self.trace.band);
if result.is_ok() { if result.is_ok() {
self.tracer.undo_step(&mut self.trace); self.tracer.undo_step(&mut self.trace);
@ -134,17 +120,17 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 { fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 {
self.observer.on_estimate(&self.tracer, vertex); self.observer.on_estimate(&self.tracer, vertex);
let start_point = GeometryIndex::from(vertex) let start_point = GeometryIndex::from(vertex)
.primitive(self.tracer.layout) .primitive(&self.tracer.board.layout)
.shape() .shape()
.center(); .center();
let end_point = self.tracer.layout.primitive(self.to).shape().center(); let end_point = self.tracer.board.layout.primitive(self.to).shape().center();
end_point.euclidean_distance(&start_point) end_point.euclidean_distance(&start_point)
} }
} }
impl<R: RulesTrait> Router<R> { impl<R: RulesTrait> Router<R> {
pub fn new(layout: Layout<R>) -> Self { pub fn new(board: Board<R>) -> Self {
Router { layout } Router { board }
} }
pub fn route_band( pub fn route_band(
@ -157,16 +143,17 @@ impl<R: RulesTrait> Router<R> {
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
// right. // right.
//self.mesh.triangulate(&self.layout)?; //self.mesh.triangulate(&self.layout)?;
let mut mesh = Mesh::new(&self.layout); let mut mesh = Mesh::new(&self.board.layout);
mesh.generate(&self.layout).map_err(|err| RoutingError { mesh.generate(&self.board.layout)
from, .map_err(|err| RoutingError {
to, from,
source: err.into(), to,
})?; source: err.into(),
})?;
let mut tracer = self.tracer(&mesh); let mut tracer = self.tracer(&mesh);
let trace = tracer.start(from, width); let trace = tracer.start(from, width);
let band = trace.head.band(); let band = trace.band;
let (_cost, _path) = astar( let (_cost, _path) = astar(
&mesh, &mesh,
@ -189,14 +176,14 @@ impl<R: RulesTrait> Router<R> {
width: f64, width: f64,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> { ) -> Result<BandIndex, RoutingError> {
let from_dot = self.layout.band(band).from(); let from_dot = self.board.band_from(band);
let to_dot = self.layout.band(band).to().unwrap(); let to_dot = self.board.band_to(band).unwrap();
self.layout.remove_band(band); self.board.remove_band(band);
self.layout.move_dot(to_dot.into(), to).unwrap(); // TODO: Remove `.unwrap()`. self.board.layout.move_dot(to_dot.into(), to).unwrap(); // TODO: Remove `.unwrap()`.
self.route_band(from_dot, to_dot, width, observer) self.route_band(from_dot, to_dot, width, observer)
} }
pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer<R> { pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer<R> {
Tracer::new(&mut self.layout, mesh) Tracer::new(&mut self.board, mesh)
} }
} }

View File

@ -1,13 +1,14 @@
use contracts::debug_ensures; use contracts::debug_ensures;
use crate::{ use crate::{
board::{connectivity::BandIndex, Board},
draw::{Draw, DrawException}, draw::{Draw, DrawException},
layout::{ layout::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::FixedDotIndex, dot::FixedDotIndex,
guide::{BareHead, Head, SegbendHead}, graph::{GetNet, MakePrimitive},
guide::{BareHead, Head, HeadTrait, SegbendHead},
rules::RulesTrait, rules::RulesTrait,
Layout,
}, },
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
}; };
@ -16,23 +17,27 @@ use crate::{
pub struct Trace { pub struct Trace {
pub path: Vec<VertexIndex>, pub path: Vec<VertexIndex>,
pub head: Head, pub head: Head,
pub band: BandIndex,
pub width: f64,
} }
pub struct Tracer<'a, R: RulesTrait> { pub struct Tracer<'a, R: RulesTrait> {
pub layout: &'a mut Layout<R>, pub board: &'a mut Board<R>,
pub mesh: &'a Mesh, pub mesh: &'a Mesh,
} }
impl<'a, R: RulesTrait> Tracer<'a, R> { impl<'a, R: RulesTrait> Tracer<'a, R> {
pub fn new(layout: &'a mut Layout<R>, mesh: &'a Mesh) -> Self { pub fn new(board: &'a mut Board<R>, mesh: &'a Mesh) -> Self {
Tracer { layout, mesh } Tracer { board, mesh }
} }
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {
let band = self.layout.add_band(from, width); let band = self.board.start_band(from);
Trace { Trace {
path: vec![from.into()], path: vec![from.into()],
head: BareHead { dot: from, band }.into(), head: BareHead { dot: from }.into(),
band,
width,
} }
} }
@ -42,7 +47,8 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
into: FixedDotIndex, into: FixedDotIndex,
width: f64, width: f64,
) -> Result<(), DrawException> { ) -> Result<(), DrawException> {
self.draw().finish_in_dot(trace.head, into, width) self.draw().finish_in_dot(trace.head, into, width)?;
Ok(self.board.finish_band(trace.band, into))
} }
#[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())] #[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())]
@ -152,6 +158,6 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
} }
fn draw(&mut self) -> Draw<R> { fn draw(&mut self) -> Draw<R> {
Draw::new(&mut self.layout) Draw::new(&mut self.board.layout)
} }
} }