board,layout: rename "layout" to "drawing", "board" to "layout"

This commit is contained in:
Mikolaj Wielgus 2024-03-22 23:23:31 +00:00
parent 4cb429ca6d
commit ef823c1c27
32 changed files with 1152 additions and 1135 deletions

View File

@ -5,9 +5,9 @@ use std::{
}; };
use topola::{ use topola::{
drawing::{graph::MakePrimitive, primitive::MakeShape, Drawing},
dsn::{design::DsnDesign, rules::DsnRules}, dsn::{design::DsnDesign, rules::DsnRules},
geometry::shape::{BendShape, DotShape, SegShape, Shape}, geometry::shape::{BendShape, DotShape, SegShape, Shape},
layout::{graph::MakePrimitive, primitive::MakeShape, Layout},
math::Circle, math::Circle,
}; };
@ -24,7 +24,7 @@ pub struct App {
text_channel: (Sender<String>, Receiver<String>), text_channel: (Sender<String>, Receiver<String>),
#[serde(skip)] #[serde(skip)]
layout: Option<Layout<DsnRules>>, drawing: Option<Drawing<DsnRules>>,
#[serde(skip)] #[serde(skip)]
from_rect: egui::emath::Rect, from_rect: egui::emath::Rect,
@ -36,7 +36,7 @@ impl Default for App {
// Example stuff: // Example stuff:
label: "Hello World!".to_owned(), label: "Hello World!".to_owned(),
text_channel: channel(), text_channel: channel(),
layout: None, drawing: None,
from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0), from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0),
} }
} }
@ -65,12 +65,12 @@ impl eframe::App for App {
if cfg!(target_arch = "wasm32") { if cfg!(target_arch = "wasm32") {
if let Ok(file_contents) = self.text_channel.1.try_recv() { if let Ok(file_contents) = self.text_channel.1.try_recv() {
let design = DsnDesign::load_from_string(file_contents).unwrap(); let design = DsnDesign::load_from_string(file_contents).unwrap();
self.layout = Some(design.make_layout()); self.drawing = Some(design.make_drawing());
} }
} else { } else {
if let Ok(path) = self.text_channel.1.try_recv() { if let Ok(path) = self.text_channel.1.try_recv() {
let design = DsnDesign::load_from_file(&path).unwrap(); let design = DsnDesign::load_from_file(&path).unwrap();
self.layout = Some(design.make_layout()); self.drawing = Some(design.make_drawing());
} }
} }
@ -138,7 +138,7 @@ impl eframe::App for App {
let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect); let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect);
let mut painter = Painter::new(ui, transform); let mut painter = Painter::new(ui, transform);
if let Some(layout) = &self.layout { if let Some(layout) = &self.drawing {
for node in layout.layer_nodes(1) { for node in layout.layer_nodes(1) {
let shape = node.primitive(layout).shape(); let shape = node.primitive(layout).shape();
painter.paint_shape(&shape, egui::Color32::from_rgb(52, 52, 200)); painter.paint_shape(&shape, egui::Color32::from_rgb(52, 52, 200));

View File

@ -12,17 +12,17 @@ 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::drawing::dot::FixedDotWeight;
use topola::drawing::graph::{GeometryIndex, MakePrimitive};
use topola::drawing::primitive::MakeShape;
use topola::drawing::rules::{Conditions, RulesTrait};
use topola::drawing::seg::FixedSegWeight;
use topola::drawing::{Drawing, Infringement, LayoutException};
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::dot::FixedDotWeight; use topola::layout::connectivity::BandIndex;
use topola::layout::graph::{GeometryIndex, MakePrimitive}; use topola::layout::Layout;
use topola::layout::primitive::MakeShape;
use topola::layout::rules::{Conditions, RulesTrait};
use topola::layout::seg::FixedSegWeight;
use topola::layout::{Infringement, Layout, LayoutException};
use topola::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use topola::mesh::{Mesh, MeshEdgeReference, VertexIndex};
use topola::router::RouterObserverTrait; use topola::router::RouterObserverTrait;
@ -76,7 +76,7 @@ impl RulesTrait for SimpleRules {
// Clunky enum to work around borrow checker. // Clunky enum to work around borrow checker.
enum RouterOrLayout<'a, R: RulesTrait> { enum RouterOrLayout<'a, R: RulesTrait> {
Router(&'a mut Router<R>), Router(&'a mut Router<R>),
Layout(&'a Layout<R>), Layout(&'a Drawing<R>),
} }
struct EmptyRouterObserver; struct EmptyRouterObserver;
@ -129,7 +129,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.renderer, self.renderer,
self.font_context, self.font_context,
self.view, self.view,
RouterOrLayout::Layout(tracer.board.layout()), RouterOrLayout::Layout(tracer.layout.layout()),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
@ -148,7 +148,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.renderer, self.renderer,
self.font_context, self.font_context,
self.view, self.view,
RouterOrLayout::Layout(tracer.board.layout()), RouterOrLayout::Layout(tracer.layout.layout()),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&path, &path,
@ -180,7 +180,7 @@ impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
self.renderer, self.renderer,
self.font_context, self.font_context,
self.view, self.view,
RouterOrLayout::Layout(tracer.board.layout()), RouterOrLayout::Layout(tracer.layout.layout()),
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
@ -256,9 +256,9 @@ fn main() -> Result<(), anyhow::Error> {
)?; )?;
//let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?; //let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?;
//dbg!(&design); //dbg!(&design);
let layout = design.make_layout(); let drawing = design.make_drawing();
let board = Board::new(layout); let layout = Layout::new(drawing);
let mut router = Router::new(board); let mut router = Router::new(layout);
let mut view = View { let mut view = View {
pan: vec2f(-80000.0, -60000.0), pan: vec2f(-80000.0, -60000.0),
@ -271,7 +271,7 @@ fn main() -> Result<(), anyhow::Error> {
&mut renderer, &mut renderer,
&font_context, &font_context,
&mut view, &mut view,
RouterOrLayout::Layout(router.board.layout()), RouterOrLayout::Layout(router.layout.layout()),
None, None,
None, None,
&[], &[],
@ -295,7 +295,7 @@ fn main() -> Result<(), anyhow::Error> {
&mut renderer, &mut renderer,
&font_context, &font_context,
&mut view, &mut view,
RouterOrLayout::Layout(router.board.layout()), RouterOrLayout::Layout(router.layout.layout()),
None, None,
None, None,
&[], &[],
@ -388,7 +388,7 @@ fn render_times(
maybe_mesh = None; maybe_mesh = None;
} }
router.board.layout() router.layout.layout()
} }
RouterOrLayout::Layout(layout) => layout, RouterOrLayout::Layout(layout) => layout,
}; };

View File

@ -1,118 +0,0 @@
use geo::Point;
use petgraph::stable_graph::StableDiGraph;
use crate::{
graph::GetNodeIndex,
layout::{
bend::LooseBendWeight,
dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight},
rules::RulesTrait,
seg::{LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight},
segbend::Segbend,
Infringement, Layout, LayoutException,
},
wraparoundable::WraparoundableIndex,
};
use super::connectivity::{
BandIndex, BandWeight, ConnectivityLabel, ConnectivityWeight, ContinentIndex,
};
pub struct Board<R: RulesTrait> {
layout: Layout<R>, // Shouldn't be public, but is for now because `Draw` needs it.
connectivity: StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>,
}
impl<R: RulesTrait> Board<R> {
pub fn new(layout: Layout<R>) -> Self {
Self {
layout,
connectivity: StableDiGraph::default(),
}
}
pub fn remove_band(&mut self, band: BandIndex) {
todo!()
}
pub fn remove_segbend(&mut self, segbend: &Segbend, face: LooseDotIndex) {
self.layout.remove_segbend(segbend, face)
}
pub fn start_band(&mut self, from: FixedDotIndex) -> BandIndex {
let band = self
.connectivity
.add_node(ConnectivityWeight::Band(BandWeight { from, to: None }));
self.connectivity.update_edge(
self.continent(from.into()).node_index(),
band,
ConnectivityLabel::Band,
);
BandIndex::new(band)
}
pub fn finish_band(&mut self, band: BandIndex, to: FixedDotIndex) {
self.connectivity.update_edge(
band.node_index(),
self.continent(to.into()).node_index(),
ConnectivityLabel::Band,
);
}
pub fn insert_segbend(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Segbend, LayoutException> {
self.layout
.insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw)
}
pub fn add_lone_loose_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> {
self.layout.add_lone_loose_seg(from, to, weight)
}
pub fn add_seq_loose_seg(
&mut self,
from: DotIndex,
to: LooseDotIndex,
weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> {
self.layout.add_seq_loose_seg(from, to, weight)
}
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
self.layout.move_dot(dot, to)
}
pub fn band_from(&self, band: BandIndex) -> FixedDotIndex {
todo!()
}
pub fn band_to(&self, band: BandIndex) -> Option<FixedDotIndex> {
todo!()
}
pub fn band_length(&self, band: BandIndex) -> f64 {
// TODO.
0.0
}
pub fn layout(&self) -> &Layout<R> {
&self.layout
}
pub fn continent(&self, dot: FixedDotIndex) -> ContinentIndex {
// TODO.
ContinentIndex::new(0.into())
}
}

View File

@ -1,4 +0,0 @@
mod board;
pub mod connectivity;
pub use board::*;

View File

@ -3,8 +3,7 @@ use geo::{EuclideanLength, Point};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
board::Board, drawing::{
layout::{
bend::{BendIndex, LooseBendWeight}, bend::{BendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight},
graph::{GetLayer, GetNet, MakePrimitive}, graph::{GetLayer, GetNet, MakePrimitive},
@ -14,6 +13,7 @@ use crate::{
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
Infringement, LayoutException, Infringement, LayoutException,
}, },
layout::Layout,
math::{Circle, NoTangents}, math::{Circle, NoTangents},
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
}; };
@ -31,20 +31,20 @@ pub enum DrawException {
} }
pub struct Draw<'a, R: RulesTrait> { pub struct Draw<'a, R: RulesTrait> {
board: &'a mut Board<R>, layout: &'a mut Layout<R>,
} }
impl<'a, R: RulesTrait> Draw<'a, R> { impl<'a, R: RulesTrait> Draw<'a, R> {
pub fn new(board: &'a mut Board<R>) -> Self { pub fn new(layout: &'a mut Layout<R>) -> Self {
Self { board } Self { layout }
} }
pub fn start(&mut self, from: LooseDotIndex) -> Head { pub fn start(&mut self, from: LooseDotIndex) -> Head {
self.guide().segbend_head(from).into() self.guide().segbend_head(from).into()
} }
#[debug_ensures(ret.is_ok() -> self.board.layout().node_count() == old(self.board.layout().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
pub fn finish_in_dot( pub fn finish_in_dot(
&mut self, &mut self,
head: Head, head: Head,
@ -58,17 +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 layer = head.face().primitive(self.board.layout()).layer(); let layer = head.face().primitive(self.layout.layout()).layer();
let net = head.face().primitive(self.board.layout()).net(); let net = head.face().primitive(self.layout.layout()).net();
match head.face() { match head.face() {
DotIndex::Fixed(dot) => { DotIndex::Fixed(dot) => {
self.board self.layout
.add_lone_loose_seg(dot, into.into(), LoneLooseSegWeight { width, layer, net }) .add_lone_loose_seg(dot, into.into(), LoneLooseSegWeight { width, layer, net })
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
} }
DotIndex::Loose(dot) => { DotIndex::Loose(dot) => {
self.board self.layout
.add_seq_loose_seg(into.into(), dot, SeqLooseSegWeight { width, layer, net }) .add_seq_loose_seg(into.into(), dot, SeqLooseSegWeight { width, layer, net })
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
} }
@ -76,8 +76,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
Ok::<(), DrawException>(()) Ok::<(), DrawException>(())
} }
#[debug_ensures(ret.is_ok() -> self.board.layout().node_count() == old(self.board.layout().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() + 4))]
#[debug_ensures(ret.is_err() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
pub fn segbend_around_dot( pub fn segbend_around_dot(
&mut self, &mut self,
head: Head, head: Head,
@ -121,8 +121,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
)) ))
} }
#[debug_ensures(ret.is_ok() -> self.board.layout().node_count() == old(self.board.layout().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() + 4))]
#[debug_ensures(ret.is_err() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
pub fn segbend_around_bend( pub fn segbend_around_bend(
&mut self, &mut self,
head: Head, head: Head,
@ -166,8 +166,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
)) ))
} }
#[debug_ensures(ret.is_ok() -> self.board.layout().node_count() == old(self.board.layout().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() + 4))]
#[debug_ensures(ret.is_err() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
fn segbend_around( fn segbend_around(
&mut self, &mut self,
head: Head, head: Head,
@ -182,18 +182,18 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
self.segbend(head, around, to, cw, width, offset) self.segbend(head, around, to, cw, width, offset)
} }
#[debug_ensures(self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, Infringement> { fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, Infringement> {
if let Head::Segbend(head) = head { if let Head::Segbend(head) = head {
self.board.move_dot(head.face.into(), to)?; self.layout.move_dot(head.face.into(), to)?;
Ok(Head::Segbend(head)) Ok(Head::Segbend(head))
} else { } else {
Ok(head) Ok(head)
} }
} }
#[debug_ensures(ret.is_ok() -> self.board.layout().node_count() == old(self.board.layout().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() + 4))]
#[debug_ensures(ret.is_err() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
fn segbend( fn segbend(
&mut self, &mut self,
head: Head, head: Head,
@ -203,9 +203,9 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
width: f64, width: f64,
offset: f64, offset: f64,
) -> Result<SegbendHead, LayoutException> { ) -> Result<SegbendHead, LayoutException> {
let layer = head.face().primitive(self.board.layout()).layer(); let layer = head.face().primitive(self.layout.layout()).layer();
let net = head.face().primitive(self.board.layout()).net(); let net = head.face().primitive(self.layout.layout()).net();
let segbend = self.board.insert_segbend( let segbend = self.layout.insert_segbend(
head.face(), head.face(),
around, around,
LooseDotWeight { LooseDotWeight {
@ -227,7 +227,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
)?; )?;
Ok::<SegbendHead, LayoutException>(SegbendHead { Ok::<SegbendHead, LayoutException>(SegbendHead {
face: self face: self
.board .layout
.layout() .layout()
.primitive(segbend.bend) .primitive(segbend.bend)
.other_joint(segbend.dot), .other_joint(segbend.dot),
@ -235,20 +235,20 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
}) })
} }
#[debug_ensures(ret.is_some() -> self.board.layout().node_count() == old(self.board.layout().node_count() - 4))] #[debug_ensures(ret.is_some() -> self.layout.layout().node_count() == old(self.layout.layout().node_count() - 4))]
#[debug_ensures(ret.is_none() -> self.board.layout().node_count() == old(self.board.layout().node_count()))] #[debug_ensures(ret.is_none() -> self.layout.layout().node_count() == old(self.layout.layout().node_count()))]
pub fn undo_segbend(&mut self, head: SegbendHead) -> Option<Head> { pub fn undo_segbend(&mut self, head: SegbendHead) -> Option<Head> {
let prev_dot = self let prev_dot = self
.board .layout
.layout() .layout()
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_joint(head.segbend.dot.into()); .other_joint(head.segbend.dot.into());
self.board.remove_segbend(&head.segbend, head.face); self.layout.remove_segbend(&head.segbend, head.face);
Some(self.guide().head(prev_dot)) Some(self.guide().head(prev_dot))
} }
fn guide(&self) -> Guide<R> { fn guide(&self) -> Guide<R> {
Guide::new(self.board.layout()) Guide::new(self.layout.layout())
} }
} }

View File

@ -1,14 +1,14 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use crate::{ use crate::{
geometry::{BendWeightTrait, GetOffset, GetWidth, SetOffset}, drawing::{
graph::{GenericIndex, GetNodeIndex},
layout::{
graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag}, graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Drawing,
}, },
geometry::{BendWeightTrait, GetOffset, GetWidth, SetOffset},
graph::{GenericIndex, GetNodeIndex},
}; };
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;

View File

@ -5,32 +5,32 @@ use super::{
graph::GeometryIndex, graph::GeometryIndex,
primitive::{GetInnerOuter, GetJoints}, primitive::{GetInnerOuter, GetJoints},
rules::RulesTrait, rules::RulesTrait,
Layout, Drawing,
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct Collect<'a, R: RulesTrait> { pub struct Collect<'a, R: RulesTrait> {
layout: &'a Layout<R>, drawing: &'a Drawing<R>,
} }
impl<'a, R: RulesTrait> Collect<'a, R> { impl<'a, R: RulesTrait> Collect<'a, R> {
pub fn new(layout: &'a Layout<R>) -> Self { pub fn new(drawing: &'a Drawing<R>) -> Self {
Self { layout } Self { drawing }
} }
pub fn bend_bow(&self, bend: LooseBendIndex) -> Vec<GeometryIndex> { pub fn bend_bow(&self, bend: LooseBendIndex) -> Vec<GeometryIndex> {
let mut v: Vec<GeometryIndex> = vec![]; let mut v: Vec<GeometryIndex> = vec![];
v.push(bend.into()); v.push(bend.into());
let ends = self.layout.primitive(bend).joints(); let ends = self.drawing.primitive(bend).joints();
v.push(ends.0.into()); v.push(ends.0.into());
v.push(ends.1.into()); v.push(ends.1.into());
if let Some(seg0) = self.layout.primitive(ends.0).seg() { if let Some(seg0) = self.drawing.primitive(ends.0).seg() {
v.push(seg0.into()); v.push(seg0.into());
} }
if let Some(seg1) = self.layout.primitive(ends.1).seg() { if let Some(seg1) = self.drawing.primitive(ends.1).seg() {
v.push(seg1.into()); v.push(seg1.into());
} }
@ -41,7 +41,7 @@ impl<'a, R: RulesTrait> Collect<'a, R> {
let mut v = vec![]; let mut v = vec![];
let mut rail = bend; let mut rail = bend;
while let Some(outer) = self.layout.primitive(rail).outer() { while let Some(outer) = self.drawing.primitive(rail).outer() {
v.append(&mut self.bend_bow(outer.into())); v.append(&mut self.bend_bow(outer.into()));
rail = outer; rail = outer;
} }
@ -53,8 +53,8 @@ impl<'a, R: RulesTrait> Collect<'a, R> {
let mut v = vec![]; let mut v = vec![];
let mut rail = around.into(); let mut rail = around.into();
while let Some(outer) = self.layout.wraparoundable(rail).wraparound() { while let Some(outer) = self.drawing.wraparoundable(rail).wraparound() {
let primitive = self.layout.primitive(outer); let primitive = self.drawing.primitive(outer);
v.push(outer.into()); v.push(outer.into());
@ -62,8 +62,8 @@ impl<'a, R: RulesTrait> Collect<'a, R> {
v.push(ends.0.into()); v.push(ends.0.into());
v.push(ends.1.into()); v.push(ends.1.into());
v.push(self.layout.primitive(ends.0).seg().unwrap().into()); v.push(self.drawing.primitive(ends.0).seg().unwrap().into());
v.push(self.layout.primitive(ends.1).seg().unwrap().into()); v.push(self.drawing.primitive(ends.1).seg().unwrap().into());
rail = outer.into(); rail = outer.into();
} }

View File

@ -4,14 +4,14 @@ use geo::Point;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
geometry::{DotWeightTrait, GetPos, GetWidth, SetPos}, drawing::{
graph::{GenericIndex, GetNodeIndex},
layout::{
graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag}, graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Drawing,
}, },
geometry::{DotWeightTrait, GetPos, GetWidth, SetPos},
graph::{GenericIndex, GetNodeIndex},
math::Circle, math::Circle,
}; };

823
src/drawing/drawing.rs Normal file
View File

@ -0,0 +1,823 @@
use contracts::debug_ensures;
use enum_dispatch::enum_dispatch;
use geo::Point;
use rstar::{RTreeObject, AABB};
use thiserror::Error;
use super::graph::GetLayer;
use super::loose::{GetNextLoose, Loose, LooseIndex};
use super::rules::RulesTrait;
use super::segbend::Segbend;
use crate::drawing::bend::BendIndex;
use crate::drawing::collect::Collect;
use crate::drawing::dot::DotWeight;
use crate::drawing::graph::GetNet;
use crate::drawing::guide::Guide;
use crate::drawing::primitive::GetLimbs;
use crate::drawing::rules::GetConditions;
use crate::drawing::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
graph::{GeometryIndex, GeometryWeight, MakePrimitive},
primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape},
seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SeqLooseSegIndex, SeqLooseSegWeight,
},
};
use crate::geometry::{
shape::{Shape, ShapeTrait},
with_rtree::GeometryWithRtree,
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetOffset, GetPos, GetWidth,
SegWeightTrait,
};
use crate::graph::{GenericIndex, GetNodeIndex};
use crate::math::NoTangents;
use crate::wraparoundable::{GetWraparound, Wraparoundable, WraparoundableIndex};
use super::bend::BendWeight;
use super::seg::SegWeight;
#[enum_dispatch]
#[derive(Error, Debug, Clone, Copy)]
pub enum LayoutException {
#[error(transparent)]
NoTangents(#[from] NoTangents),
#[error(transparent)]
Infringement(#[from] Infringement),
#[error(transparent)]
Collision(#[from] Collision),
#[error(transparent)]
AlreadyConnected(#[from] AlreadyConnected),
}
// TODO add real error messages + these should eventually use Display
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} infringes on {1:?}")]
pub struct Infringement(pub Shape, pub GeometryIndex);
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} collides with {1:?}")]
pub struct Collision(pub Shape, pub GeometryIndex);
#[derive(Error, Debug, Clone, Copy)]
#[error("{1:?} is already connected to net {0}")]
pub struct AlreadyConnected(pub i64, pub GeometryIndex);
#[derive(Debug)]
pub struct Drawing<R: RulesTrait> {
geometry_with_rtree: GeometryWithRtree<
GeometryWeight,
DotWeight,
SegWeight,
BendWeight,
GeometryIndex,
DotIndex,
SegIndex,
BendIndex,
>,
rules: R,
}
impl<R: RulesTrait> Drawing<R> {
pub fn new(rules: R) -> Self {
Self {
geometry_with_rtree: GeometryWithRtree::new(2),
rules,
}
}
pub fn remove_band(&mut self, first_loose: SeqLooseSegIndex) {
let mut dots = vec![];
let mut segs = vec![];
let mut bends = vec![];
let mut outers = vec![];
let mut maybe_loose = Some(first_loose.into());
let mut prev = None;
while let Some(loose) = maybe_loose {
match loose {
LooseIndex::Dot(dot) => {
dots.push(dot);
}
LooseIndex::LoneSeg(seg) => {
self.geometry_with_rtree.remove_seg(seg.into());
break;
}
LooseIndex::SeqSeg(seg) => {
segs.push(seg);
}
LooseIndex::Bend(bend) => {
bends.push(bend);
if let Some(outer) = self.primitive(bend).outer() {
outers.push(outer);
self.reattach_bend(outer, self.primitive(bend).inner());
}
}
}
let prev_prev = prev;
prev = maybe_loose;
maybe_loose = self.loose(loose).next_loose(prev_prev);
}
for bend in bends {
self.geometry_with_rtree.remove_bend(bend.into());
}
for seg in segs {
self.geometry_with_rtree.remove_seg(seg.into());
}
// We must remove the dots only after the segs and bends because we need dots to calculate
// the shapes, which we first need unchanged to remove the segs and bends from the R-tree.
for dot in dots {
self.geometry_with_rtree.remove_dot(dot.into());
}
for outer in outers {
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
}
}
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 4))]
pub fn remove_segbend(&mut self, segbend: &Segbend, face: LooseDotIndex) {
let maybe_outer = self.primitive(segbend.bend).outer();
// Removing a loose bend affects its outer bends.
if let Some(outer) = maybe_outer {
self.reattach_bend(outer, self.primitive(segbend.bend).inner());
}
self.geometry_with_rtree.remove_bend(segbend.bend.into());
self.geometry_with_rtree.remove_seg(segbend.seg.into());
// We must remove the dots only after the segs and bends because we need dots to calculate
// the shapes, which we first need unchanged to remove the segs and bends from the R-tree.
self.geometry_with_rtree.remove_dot(face.into());
self.geometry_with_rtree.remove_dot(segbend.dot.into());
if let Some(outer) = maybe_outer {
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
}
}
#[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(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
self.add_dot_infringably(weight, None)
}
#[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()))]
fn add_dot_infringably<W: DotWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
weight: W,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let dot = self.geometry_with_rtree.add_dot(weight);
self.fail_and_remove_if_infringes_except(dot.into(), infringables)?;
Ok(dot)
}
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> Result<FixedSegIndex, Infringement> {
self.add_seg_infringably(from.into(), to.into(), weight, None)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn insert_segbend(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Segbend, LayoutException> {
let maybe_wraparound = self.wraparoundable(around).wraparound();
let infringables = self.collect().wraparounded_bows(around);
let segbend = self.add_segbend_infringably(
from,
around,
dot_weight,
seg_weight,
bend_weight,
cw,
Some(&infringables),
)?;
if let Some(wraparound) = maybe_wraparound {
self.reattach_bend(wraparound, Some(segbend.bend));
}
if let Some(outer) = self.primitive(segbend.bend).outer() {
self.update_this_and_outward_bows(outer).map_err(|err| {
let joint = self.primitive(segbend.bend).other_joint(segbend.dot);
self.remove_segbend(&segbend, joint.into());
err
})?;
}
// Segs must not cross.
if let Some(collision) = self.detect_collision(segbend.seg.into()) {
let joint = self.primitive(segbend.bend).other_joint(segbend.dot);
self.remove_segbend(&segbend, joint.into());
return Err(collision.into());
}
Ok::<Segbend, LayoutException>(segbend)
}
#[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())
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() - 1)
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 1))]
fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option<LooseBendIndex>) {
self.geometry_with_rtree
.reattach_bend(bend.into(), maybe_new_inner.map(Into::into));
}
#[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()))]
fn update_this_and_outward_bows(
&mut self,
around: LooseBendIndex,
) -> Result<(), LayoutException> {
// FIXME: Fail gracefully on infringement.
let mut maybe_rail = Some(around);
while let Some(rail) = maybe_rail {
let rail_primitive = self.primitive(rail);
let joints = rail_primitive.joints();
let guide = Guide::new(self);
let from_head = guide.rear_head(joints.1);
let to_head = guide.rear_head(joints.0);
if let Some(inner) = rail_primitive.inner() {
let from = guide
.head_around_bend_segment(
&from_head.into(),
inner.into(),
true,
self.primitive(rail).width(),
)?
.end_point();
let to = guide
.head_around_bend_segment(
&to_head.into(),
inner.into(),
false,
self.primitive(rail).width(),
)?
.end_point();
let offset = guide.head_around_bend_offset(
&from_head.into(),
inner.into(),
self.primitive(rail).width(),
);
self.move_dot_infringably(
joints.0.into(),
from,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.move_dot_infringably(
joints.1.into(),
to,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.shift_bend_infringably(
rail.into(),
offset,
Some(&self.collect().bend_outer_bows(rail)),
)?;
// Update offsets in case the rule conditions changed.
} else {
let core = rail_primitive.core();
let from = guide
.head_around_dot_segment(
&from_head.into(),
core.into(),
true,
self.primitive(rail).width(),
)?
.end_point();
let to = guide
.head_around_dot_segment(
&to_head.into(),
core.into(),
false,
self.primitive(rail).width(),
)?
.end_point();
let offset = guide.head_around_dot_offset(
&from_head.into(),
core.into(),
self.primitive(rail).width(),
);
self.move_dot_infringably(
joints.0.into(),
from,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.move_dot_infringably(
joints.1.into(),
to,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.shift_bend_infringably(
rail.into(),
offset,
Some(&self.collect().bend_outer_bows(rail)),
)?;
}
maybe_rail = self.primitive(rail).outer();
}
Ok::<(), LayoutException>(())
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_segbend(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Segbend, LayoutException> {
self.add_segbend_infringably(
from,
around,
dot_weight,
seg_weight,
bend_weight,
cw,
Some(&self.collect().wraparounded_bows(around)),
)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_segbend_infringably(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
infringables: Option<&[GeometryIndex]>,
) -> Result<Segbend, LayoutException> {
let seg_to = self.add_dot_infringably(dot_weight, infringables)?;
let seg = self
.add_seg_infringably(from, seg_to.into(), seg_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
let to = self
.add_dot_infringably(dot_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_seg(seg.into());
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
let (bend_from, bend_to) = if cw { (to, seg_to) } else { (seg_to, to) };
let bend = self
.add_loose_bend_infringably(bend_from, bend_to, around, bend_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_dot(to.into());
self.geometry_with_rtree.remove_seg(seg.into());
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
Ok::<Segbend, LayoutException>(Segbend {
seg,
dot: seg_to,
bend,
})
}
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_lone_loose_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from.into(), to.into(), weight, Some(&[]))?;
Ok(seg)
}
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_seq_loose_seg(
&mut self,
from: DotIndex,
to: LooseDotIndex,
weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from, to.into(), weight, Some(&[]))?;
Ok(seg)
}
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_seg_infringably<W: SegWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let seg = self.geometry_with_rtree.add_seg(from, to, weight);
self.fail_and_remove_if_infringes_except(seg.into(), infringables)?;
Ok(seg)
}
#[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)
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_loose_bend_infringably(
&mut self,
from: LooseDotIndex,
to: LooseDotIndex,
around: WraparoundableIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
) -> Result<LooseBendIndex, LayoutException> {
// It makes no sense to wrap something around or under one of its connectables.
//
if weight.net == around.primitive(self).net() {
return Err(AlreadyConnected(weight.net, around.into()).into());
}
//
if let Some(wraparound) = self.wraparoundable(around).wraparound() {
if weight.net == wraparound.primitive(self).net() {
return Err(AlreadyConnected(weight.net, wraparound.into()).into());
}
}
match around {
WraparoundableIndex::FixedDot(core) => self
.add_core_bend_infringably(from.into(), to.into(), core, weight, infringables)
.map_err(Into::into),
WraparoundableIndex::FixedBend(around) => self
.add_outer_bend_infringably(from, to, around.into(), weight, infringables)
.map_err(Into::into),
WraparoundableIndex::LooseBend(around) => self
.add_outer_bend_infringably(from, to, around.into(), weight, infringables)
.map_err(Into::into),
}
}
#[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_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_core_bend_infringably<W: BendWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
core: FixedDotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let bend = self
.geometry_with_rtree
.add_bend(from, to, core.into(), weight);
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend)
}
#[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_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_outer_bend_infringably(
&mut self,
from: LooseDotIndex,
to: LooseDotIndex,
inner: BendIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<LooseBendWeight>, Infringement> {
let core = *self
.geometry_with_rtree
.graph()
.neighbors(inner.node_index())
.filter(|ni| {
matches!(
self.geometry_with_rtree
.graph()
.edge_weight(
self.geometry_with_rtree
.graph()
.find_edge(inner.node_index(), *ni)
.unwrap()
)
.unwrap(),
GeometryLabel::Core
)
})
.map(|ni| FixedDotIndex::new(ni))
.collect::<Vec<FixedDotIndex>>()
.first()
.unwrap();
let bend = self
.geometry_with_rtree
.add_bend(from.into(), to.into(), core.into(), weight);
self.geometry_with_rtree
.reattach_bend(bend.into(), Some(inner));
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend)
}
#[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 flip_bend(&mut self, bend: FixedBendIndex) {
self.geometry_with_rtree.flip_bend(bend.into());
}
pub fn segbend(&self, dot: LooseDotIndex) -> Segbend {
Segbend::from_dot(dot, self)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 1))]
fn fail_and_remove_if_infringes_except(
&mut self,
node: GeometryIndex,
maybe_except: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
if let Some(infringement) = self.detect_infringement_except(node, maybe_except) {
if let Ok(dot) = node.try_into() {
self.geometry_with_rtree.remove_dot(dot);
} else if let Ok(seg) = node.try_into() {
self.geometry_with_rtree.remove_seg(seg);
} else if let Ok(bend) = node.try_into() {
self.geometry_with_rtree.remove_bend(bend);
}
return Err(infringement);
}
Ok(())
}
pub fn nodes(&self) -> impl Iterator<Item = GeometryIndex> + '_ {
self.geometry_with_rtree
.rtree()
.iter()
.map(|wrapper| wrapper.data)
}
pub fn layer_nodes(&self, layer: u64) -> impl Iterator<Item = GeometryIndex> + '_ {
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&AABB::from_corners(
[-f64::INFINITY, -f64::INFINITY, layer as f64],
[f64::INFINITY, f64::INFINITY, layer as f64],
))
.map(|wrapper| wrapper.data)
}
pub fn node_count(&self) -> usize {
self.geometry_with_rtree.graph().node_count()
}
}
impl<R: RulesTrait> Drawing<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 move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
match dot {
DotIndex::Fixed(..) => self.move_dot_infringably(dot, to, Some(&[])),
DotIndex::Loose(..) => self.move_dot_infringably(dot, to, Some(&[])),
}
}
#[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()))]
fn move_dot_infringably(
&mut self,
dot: DotIndex,
to: Point,
infringables: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
let old_pos = self.geometry_with_rtree.geometry().dot_weight(dot).pos();
self.geometry_with_rtree.move_dot(dot, to);
for limb in dot.primitive(self).limbs() {
if let Some(infringement) = self.detect_infringement_except(limb.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.move_dot(dot, old_pos);
return Err(infringement);
}
}
if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.move_dot(dot, old_pos);
return Err(infringement);
}
Ok(())
}
#[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()))]
fn shift_bend_infringably(
&mut self,
bend: BendIndex,
offset: f64,
infringables: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
let old_offset = self
.geometry_with_rtree
.geometry()
.bend_weight(bend)
.offset();
self.geometry_with_rtree.shift_bend(bend, offset);
if let Some(infringement) = self.detect_infringement_except(bend.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.shift_bend(bend, old_offset);
return Err(infringement);
}
Ok(())
}
#[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()))]
fn detect_infringement_except(
&self,
node: GeometryIndex,
maybe_except: Option<&[GeometryIndex]>,
) -> Option<Infringement> {
let limiting_shape = node
.primitive(self)
.shape()
.inflate(self.rules.largest_clearance(node.primitive(self).net()));
let mut inflated_shape = limiting_shape; // Unused temporary value just for initialization.
let conditions = node.primitive(self).conditions();
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&limiting_shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| maybe_except.is_some_and(|except| !except.contains(&wrapper.data)))
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| {
let infringee_conditions = wrapper.data.primitive(self).conditions();
let epsilon = 1.0;
inflated_shape = node.primitive(self).shape().inflate(
(self.rules.clearance(&conditions, &infringee_conditions) - epsilon)
.clamp(0.0, f64::INFINITY),
);
inflated_shape.intersects(&wrapper.data.primitive(self).shape())
})
.map(|wrapper| wrapper.data)
.next()
.and_then(|infringee| Some(Infringement(inflated_shape, infringee)))
}
#[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()))]
fn detect_collision(&self, node: GeometryIndex) -> Option<Collision> {
let shape = node.primitive(self).shape();
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| shape.intersects(&wrapper.data.primitive(self).shape()))
.map(|wrapper| wrapper.data)
.next()
.and_then(|collidee| Some(Collision(shape, collidee)))
}
#[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()))]
fn are_connectable(&self, node1: GeometryIndex, node2: GeometryIndex) -> bool {
let node1_net = node1.primitive(self).net();
let node2_net = node2.primitive(self).net();
(node1_net == node2_net) || node1_net == -1 || node2_net == -2
}
}
impl<R: RulesTrait> Drawing<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 geometry(
&self,
) -> &Geometry<
GeometryWeight,
DotWeight,
SegWeight,
BendWeight,
GeometryIndex,
DotIndex,
SegIndex,
BendIndex,
> {
self.geometry_with_rtree.geometry()
}
#[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 rules(&self) -> &R {
&self.rules
}
#[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 guide(&self) -> Guide<R> {
Guide::new(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 collect(&self) -> Collect<R> {
Collect::new(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 primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, R> {
GenericPrimitive::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 wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable<R> {
Wraparoundable::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 loose(&self, index: LooseIndex) -> Loose<R> {
Loose::new(index, self)
}
}

View File

@ -2,11 +2,7 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{drawing::Drawing, graph::GetNodeIndex};
board::connectivity::{BandIndex, ContinentIndex},
graph::GetNodeIndex,
layout::Layout,
};
use super::{ use super::{
bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
@ -36,7 +32,7 @@ pub trait GetNet {
#[enum_dispatch] #[enum_dispatch]
pub trait MakePrimitive { pub trait MakePrimitive {
fn primitive<'a, R: RulesTrait>(&self, layout: &'a Layout<R>) -> Primitive<'a, R>; fn primitive<'a, R: RulesTrait>(&self, drawing: &'a Drawing<R>) -> Primitive<'a, R>;
} }
macro_rules! impl_weight { macro_rules! impl_weight {
@ -62,8 +58,8 @@ macro_rules! impl_weight {
pub type $index_struct = GenericIndex<$weight_struct>; pub type $index_struct = GenericIndex<$weight_struct>;
impl MakePrimitive for $index_struct { impl MakePrimitive for $index_struct {
fn primitive<'a, R: RulesTrait>(&self, layout: &'a Layout<R>) -> Primitive<'a, R> { fn primitive<'a, R: RulesTrait>(&self, drawing: &'a Drawing<R>) -> Primitive<'a, R> {
Primitive::$weight_variant(GenericPrimitive::new(*self, layout)) Primitive::$weight_variant(GenericPrimitive::new(*self, drawing))
} }
} }
}; };

8
src/drawing/groups.rs Normal file
View File

@ -0,0 +1,8 @@
use enum_dispatch::enum_dispatch;
use super::graph::GeometryIndex;
#[enum_dispatch]
pub trait GetGroups< {
fn node_groups(&self, node: GeometryIndex) -> Vec<GeometryIndex>;
}

View File

@ -2,16 +2,15 @@ use enum_dispatch::enum_dispatch;
use geo::Line; use geo::Line;
use crate::{ use crate::{
board::connectivity::BandIndex, drawing::{
geometry::shape::{Shape, ShapeTrait},
layout::{
bend::BendIndex, bend::BendIndex,
dot::{DotIndex, FixedDotIndex, LooseDotIndex}, dot::{DotIndex, FixedDotIndex, LooseDotIndex},
graph::MakePrimitive, graph::MakePrimitive,
primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape},
rules::GetConditions, rules::GetConditions,
Layout, Drawing,
}, },
geometry::shape::{Shape, ShapeTrait},
math::{self, Circle, NoTangents}, math::{self, Circle, NoTangents},
}; };
@ -58,12 +57,12 @@ impl HeadTrait for SegbendHead {
} }
pub struct Guide<'a, R: RulesTrait> { pub struct Guide<'a, R: RulesTrait> {
layout: &'a Layout<R>, drawing: &'a Drawing<R>,
} }
impl<'a, R: RulesTrait> Guide<'a, R> { impl<'a, R: RulesTrait> Guide<'a, R> {
pub fn new(layout: &'a Layout<R>) -> Self { pub fn new(drawing: &'a Drawing<R>) -> Self {
Self { layout } Self { drawing }
} }
pub fn head_into_dot_segment( pub fn head_into_dot_segment(
@ -74,7 +73,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
) -> Result<Line, NoTangents> { ) -> Result<Line, NoTangents> {
let from_circle = self.head_circle(head, width); let from_circle = self.head_circle(head, width);
let to_circle = Circle { let to_circle = Circle {
pos: self.layout.primitive(into).weight().circle.pos, pos: self.drawing.primitive(into).weight().circle.pos,
r: 0.0, r: 0.0,
}; };
@ -112,7 +111,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
} }
pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 { pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
self.layout.rules().clearance( self.drawing.rules().clearance(
&self.conditions(around.into()), &self.conditions(around.into()),
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
) )
@ -148,7 +147,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
} }
pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 { pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
self.layout.rules().clearance( self.drawing.rules().clearance(
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
&self.conditions(around.into()), &self.conditions(around.into()),
) )
@ -156,7 +155,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
pub fn head_cw(&self, head: &Head) -> Option<bool> { pub fn head_cw(&self, head: &Head) -> Option<bool> {
if let Head::Segbend(head) = head { if let Head::Segbend(head) = head {
let joints = self.layout.primitive(head.segbend.bend).joints(); let joints = self.drawing.primitive(head.segbend.bend).joints();
if head.face() == joints.0.into() { if head.face() == joints.0.into() {
Some(false) Some(false)
@ -171,15 +170,15 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
fn head_circle(&self, head: &Head, width: f64) -> Circle { fn head_circle(&self, head: &Head, width: f64) -> Circle {
match *head { match *head {
Head::Bare(head) => Circle { Head::Bare(head) => Circle {
pos: head.face().primitive(self.layout).shape().center(), // TODO. pos: head.face().primitive(self.drawing).shape().center(), // TODO.
r: 0.0, r: 0.0,
}, },
Head::Segbend(head) => { Head::Segbend(head) => {
if let Some(inner) = self.layout.primitive(head.segbend.bend).inner() { if let Some(inner) = self.drawing.primitive(head.segbend.bend).inner() {
self.bend_circle(inner.into(), width, &self.conditions(head.face().into())) self.bend_circle(inner.into(), width, &self.conditions(head.face().into()))
} else { } else {
self.dot_circle( self.dot_circle(
self.layout.primitive(head.segbend.bend).core().into(), self.drawing.primitive(head.segbend.bend).core().into(),
width, width,
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
) )
@ -189,7 +188,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
} }
fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle { fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle {
let outer_circle = match bend.primitive(self.layout).shape() { let outer_circle = match bend.primitive(self.drawing).shape() {
Shape::Bend(shape) => shape.outer_circle(), Shape::Bend(shape) => shape.outer_circle(),
_ => unreachable!(), _ => unreachable!(),
}; };
@ -199,20 +198,20 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
r: outer_circle.r r: outer_circle.r
+ width / 2.0 + width / 2.0
+ self + self
.layout .drawing
.rules() .rules()
.clearance(&self.conditions(bend.into()), guide_conditions), .clearance(&self.conditions(bend.into()), guide_conditions),
} }
} }
fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle { fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle {
let shape = dot.primitive(self.layout).shape(); let shape = dot.primitive(self.drawing).shape();
Circle { Circle {
pos: shape.center(), pos: shape.center(),
r: shape.width() / 2.0 r: shape.width() / 2.0
+ width / 2.0 + width / 2.0
+ self + self
.layout .drawing
.rules() .rules()
.clearance(&self.conditions(dot.into()), guide_conditions), .clearance(&self.conditions(dot.into()), guide_conditions),
} }
@ -221,7 +220,7 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
pub fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead { pub fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead {
SegbendHead { SegbendHead {
face: dot, face: dot,
segbend: self.layout.segbend(dot), segbend: self.drawing.segbend(dot),
} }
} }
@ -237,12 +236,12 @@ impl<'a, R: RulesTrait> Guide<'a, R> {
} }
fn rear(&self, head: SegbendHead) -> DotIndex { fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout self.drawing
.primitive(head.segbend.seg) .primitive(head.segbend.seg)
.other_joint(head.segbend.dot.into()) .other_joint(head.segbend.dot.into())
} }
fn conditions(&self, node: GeometryIndex) -> Conditions { fn conditions(&self, node: GeometryIndex) -> Conditions {
node.primitive(self.layout).conditions() node.primitive(self.drawing).conditions()
} }
} }

View File

@ -2,15 +2,15 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
graph::GetNodeIndex, drawing::Drawing,
layout::Layout, drawing::{
layout::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::{DotIndex, LooseDotIndex}, dot::{DotIndex, LooseDotIndex},
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::{GetJoints, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg}, primitive::{GetJoints, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg},
seg::{LoneLooseSegIndex, SeqLooseSegIndex}, seg::{LoneLooseSegIndex, SeqLooseSegIndex},
}, },
graph::GetNodeIndex,
}; };
use super::rules::RulesTrait; use super::rules::RulesTrait;
@ -49,12 +49,12 @@ pub enum Loose<'a, R: RulesTrait> {
} }
impl<'a, R: RulesTrait> Loose<'a, R> { impl<'a, R: RulesTrait> Loose<'a, R> {
pub fn new(index: LooseIndex, layout: &'a Layout<R>) -> Self { pub fn new(index: LooseIndex, drawing: &'a Drawing<R>) -> Self {
match index { match index {
LooseIndex::Dot(dot) => layout.primitive(dot).into(), LooseIndex::Dot(dot) => drawing.primitive(dot).into(),
LooseIndex::LoneSeg(seg) => layout.primitive(seg).into(), LooseIndex::LoneSeg(seg) => drawing.primitive(seg).into(),
LooseIndex::SeqSeg(seg) => layout.primitive(seg).into(), LooseIndex::SeqSeg(seg) => drawing.primitive(seg).into(),
LooseIndex::Bend(bend) => layout.primitive(bend).into(), LooseIndex::Bend(bend) => drawing.primitive(bend).into(),
} }
} }
} }

14
src/drawing/mod.rs Normal file
View File

@ -0,0 +1,14 @@
#[macro_use]
pub mod graph;
pub mod bend;
pub mod collect;
pub mod dot;
mod drawing;
pub mod guide;
pub mod loose;
pub mod primitive;
pub mod rules;
pub mod seg;
pub mod segbend;
pub use drawing::*;

View File

@ -1,13 +1,7 @@
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::drawing::{
use crate::geometry::{
shape::{Shape, ShapeTrait},
GetOffset, GetWidth,
};
use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::{
bend::{BendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, bend::{BendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, Retag}, graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, Retag},
@ -17,12 +11,18 @@ use crate::layout::{
FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex,
SeqLooseSegWeight, SeqLooseSegWeight,
}, },
Layout, Drawing,
}; };
use crate::geometry::{
shape::{Shape, ShapeTrait},
GetOffset, GetWidth,
};
use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::connectivity::{BandIndex, ContinentIndex};
#[enum_dispatch] #[enum_dispatch]
pub trait GetLayout<'a, R: RulesTrait> { pub trait GetDrawing<'a, R: RulesTrait> {
fn layout(&self) -> &Layout<R>; fn drawing(&self) -> &Drawing<R>;
} }
#[enum_dispatch] #[enum_dispatch]
@ -72,9 +72,9 @@ pub trait GetJoints<F, T> {
fn joints(&self) -> (F, T); fn joints(&self) -> (F, T);
} }
pub trait GetFirstRail<'a, R: RulesTrait>: GetLayout<'a, R> + GetNodeIndex { pub trait GetFirstRail<'a, R: RulesTrait>: GetDrawing<'a, R> + GetNodeIndex {
fn first_rail(&self) -> Option<LooseBendIndex> { fn first_rail(&self) -> Option<LooseBendIndex> {
self.layout() self.drawing()
.geometry() .geometry()
.first_rail(self.node_index()) .first_rail(self.node_index())
.map(|ni| LooseBendIndex::new(ni.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
@ -85,10 +85,10 @@ pub trait GetBendIndex {
fn bend_index(&self) -> BendIndex; fn bend_index(&self) -> BendIndex;
} }
pub trait GetCore<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex { pub trait GetCore<'a, R: RulesTrait>: GetDrawing<'a, R> + GetBendIndex {
fn core(&self) -> FixedDotIndex { fn core(&self) -> FixedDotIndex {
FixedDotIndex::new( FixedDotIndex::new(
self.layout() self.drawing()
.geometry() .geometry()
.core(self.bend_index()) .core(self.bend_index())
.node_index(), .node_index(),
@ -96,16 +96,16 @@ pub trait GetCore<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex {
} }
} }
pub trait GetInnerOuter<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex { pub trait GetInnerOuter<'a, R: RulesTrait>: GetDrawing<'a, R> + GetBendIndex {
fn inner(&self) -> Option<LooseBendIndex> { fn inner(&self) -> Option<LooseBendIndex> {
self.layout() self.drawing()
.geometry() .geometry()
.inner(self.bend_index()) .inner(self.bend_index())
.map(|ni| LooseBendIndex::new(ni.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
} }
fn outer(&self) -> Option<LooseBendIndex> { fn outer(&self) -> Option<LooseBendIndex> {
self.layout() self.drawing()
.geometry() .geometry()
.outer(self.bend_index()) .outer(self.bend_index())
.map(|ni| LooseBendIndex::new(ni.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
@ -172,17 +172,17 @@ pub enum Primitive<'a, R: RulesTrait> {
#[derive(Debug)] #[derive(Debug)]
pub struct GenericPrimitive<'a, W, R: RulesTrait> { pub struct GenericPrimitive<'a, W, R: RulesTrait> {
pub index: GenericIndex<W>, pub index: GenericIndex<W>,
layout: &'a Layout<R>, drawing: &'a Drawing<R>,
} }
impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> { impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
pub fn new(index: GenericIndex<W>, layout: &'a Layout<R>) -> Self { pub fn new(index: GenericIndex<W>, drawing: &'a Drawing<R>) -> Self {
Self { index, layout } Self { index, drawing }
} }
fn tagged_weight(&self) -> GeometryWeight { fn tagged_weight(&self) -> GeometryWeight {
*self *self
.layout .drawing
.geometry() .geometry()
.graph() .graph()
.node_weight(self.index.node_index()) .node_weight(self.index.node_index())
@ -190,7 +190,7 @@ impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
} }
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW, R> { fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW, R> {
GenericPrimitive::new(index, &self.layout) GenericPrimitive::new(index, &self.drawing)
} }
} }
@ -200,9 +200,9 @@ impl<'a, W, R: RulesTrait> GetInterior<GeometryIndex> for GenericPrimitive<'a, W
} }
} }
impl<'a, W, R: RulesTrait> GetLayout<'a, R> for GenericPrimitive<'a, W, R> { impl<'a, W, R: RulesTrait> GetDrawing<'a, R> for GenericPrimitive<'a, W, R> {
fn layout(&self) -> &Layout<R> { fn drawing(&self) -> &Drawing<R> {
self.layout self.drawing
} }
} }
@ -239,13 +239,13 @@ impl_fixed_primitive!(FixedDot, FixedDotWeight);
impl<'a, R: RulesTrait> FixedDot<'a, R> { impl<'a, R: RulesTrait> FixedDot<'a, R> {
pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> { pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> {
self.layout self.drawing
.geometry() .geometry()
.joineds(self.index.into()) .joineds(self.index.into())
.into_iter() .into_iter()
.find_map(|ni| { .find_map(|ni| {
let weight = self let weight = self
.layout .drawing
.geometry() .geometry()
.graph() .graph()
.node_weight(ni.node_index()) .node_weight(ni.node_index())
@ -263,20 +263,20 @@ impl<'a, R: RulesTrait> FixedDot<'a, R> {
impl<'a, R: RulesTrait> MakeShape for FixedDot<'a, R> { impl<'a, R: RulesTrait> MakeShape for FixedDot<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().dot_shape(self.index.into()) self.drawing.geometry().dot_shape(self.index.into())
} }
} }
impl<'a, R: RulesTrait> GetLimbs for FixedDot<'a, R> { impl<'a, R: RulesTrait> GetLimbs for FixedDot<'a, R> {
fn segs(&self) -> Vec<SegIndex> { fn segs(&self) -> Vec<SegIndex> {
self.layout self.drawing
.geometry() .geometry()
.joined_segs(self.index.into()) .joined_segs(self.index.into())
.collect() .collect()
} }
fn bends(&self) -> Vec<BendIndex> { fn bends(&self) -> Vec<BendIndex> {
self.layout self.drawing
.geometry() .geometry()
.joined_bends(self.index.into()) .joined_bends(self.index.into())
.collect() .collect()
@ -290,7 +290,7 @@ impl_loose_primitive!(LooseDot, LooseDotWeight);
impl<'a, R: RulesTrait> LooseDot<'a, R> { impl<'a, R: RulesTrait> LooseDot<'a, R> {
pub fn seg(&self) -> Option<SeqLooseSegIndex> { pub fn seg(&self) -> Option<SeqLooseSegIndex> {
self.layout self.drawing
.geometry() .geometry()
.joined_segs(self.index.into()) .joined_segs(self.index.into())
.map(|ni| SeqLooseSegIndex::new(ni.node_index())) .map(|ni| SeqLooseSegIndex::new(ni.node_index()))
@ -298,7 +298,7 @@ impl<'a, R: RulesTrait> LooseDot<'a, R> {
} }
pub fn bend(&self) -> LooseBendIndex { pub fn bend(&self) -> LooseBendIndex {
self.layout self.drawing
.geometry() .geometry()
.joined_bends(self.index.into()) .joined_bends(self.index.into())
.map(|ni| LooseBendIndex::new(ni.node_index())) .map(|ni| LooseBendIndex::new(ni.node_index()))
@ -309,7 +309,7 @@ impl<'a, R: RulesTrait> LooseDot<'a, R> {
impl<'a, R: RulesTrait> MakeShape for LooseDot<'a, R> { impl<'a, R: RulesTrait> MakeShape for LooseDot<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().dot_shape(self.index.into()) self.drawing.geometry().dot_shape(self.index.into())
} }
} }
@ -332,7 +332,7 @@ impl_fixed_primitive!(FixedSeg, FixedSegWeight);
impl<'a, R: RulesTrait> MakeShape for FixedSeg<'a, R> { impl<'a, R: RulesTrait> MakeShape for FixedSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.drawing.geometry().seg_shape(self.index.into())
} }
} }
@ -340,7 +340,7 @@ impl<'a, R: RulesTrait> GetLimbs for FixedSeg<'a, R> {}
impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into()); let (from, to) = self.drawing.geometry().seg_joints(self.index.into());
( (
FixedDotIndex::new(from.node_index()), FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()), FixedDotIndex::new(to.node_index()),
@ -355,7 +355,7 @@ impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight);
impl<'a, R: RulesTrait> MakeShape for LoneLooseSeg<'a, R> { impl<'a, R: RulesTrait> MakeShape for LoneLooseSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.drawing.geometry().seg_shape(self.index.into())
} }
} }
@ -363,7 +363,7 @@ impl<'a, R: RulesTrait> GetLimbs for LoneLooseSeg<'a, R> {}
impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into()); let (from, to) = self.drawing.geometry().seg_joints(self.index.into());
( (
FixedDotIndex::new(from.node_index()), FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()), FixedDotIndex::new(to.node_index()),
@ -378,7 +378,7 @@ impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight);
impl<'a, R: RulesTrait> MakeShape for SeqLooseSeg<'a, R> { impl<'a, R: RulesTrait> MakeShape for SeqLooseSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.drawing.geometry().seg_shape(self.index.into())
} }
} }
@ -386,13 +386,13 @@ impl<'a, R: RulesTrait> GetLimbs for SeqLooseSeg<'a, R> {}
impl<'a, R: RulesTrait> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> { impl<'a, R: RulesTrait> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> {
fn joints(&self) -> (DotIndex, LooseDotIndex) { fn joints(&self) -> (DotIndex, LooseDotIndex) {
let joints = self.layout.geometry().seg_joints(self.index.into()); let joints = self.drawing.geometry().seg_joints(self.index.into());
if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.0) { if let DotWeight::Fixed(..) = self.drawing.geometry().dot_weight(joints.0) {
( (
FixedDotIndex::new(joints.0.node_index()).into(), FixedDotIndex::new(joints.0.node_index()).into(),
LooseDotIndex::new(joints.1.node_index()).into(), LooseDotIndex::new(joints.1.node_index()).into(),
) )
} else if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.1) { } else if let DotWeight::Fixed(..) = self.drawing.geometry().dot_weight(joints.1) {
( (
FixedDotIndex::new(joints.1.node_index()).into(), FixedDotIndex::new(joints.1.node_index()).into(),
LooseDotIndex::new(joints.0.node_index()), LooseDotIndex::new(joints.0.node_index()),
@ -419,7 +419,7 @@ impl<'a, R: RulesTrait> GetBendIndex for FixedBend<'a, R> {
impl<'a, R: RulesTrait> MakeShape for FixedBend<'a, R> { impl<'a, R: RulesTrait> MakeShape for FixedBend<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into()) self.drawing.geometry().bend_shape(self.index.into())
} }
} }
@ -427,7 +427,7 @@ impl<'a, R: RulesTrait> GetLimbs for FixedBend<'a, R> {}
impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into()); let (from, to) = self.drawing.geometry().bend_joints(self.index.into());
( (
FixedDotIndex::new(from.node_index()), FixedDotIndex::new(from.node_index()),
FixedDotIndex::new(to.node_index()), FixedDotIndex::new(to.node_index()),
@ -457,7 +457,7 @@ impl<'a, R: RulesTrait> From<LooseBend<'a, R>> for BendIndex {
impl<'a, R: RulesTrait> MakeShape for LooseBend<'a, R> { impl<'a, R: RulesTrait> MakeShape for LooseBend<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into()) self.drawing.geometry().bend_shape(self.index.into())
} }
} }
@ -471,7 +471,7 @@ impl<'a, R: RulesTrait> GetOffset for LooseBend<'a, R> {
impl<'a, R: RulesTrait> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> { impl<'a, R: RulesTrait> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> {
fn joints(&self) -> (LooseDotIndex, LooseDotIndex) { fn joints(&self) -> (LooseDotIndex, LooseDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into()); let (from, to) = self.drawing.geometry().bend_joints(self.index.into());
( (
LooseDotIndex::new(from.node_index()), LooseDotIndex::new(from.node_index()),
LooseDotIndex::new(to.node_index()), LooseDotIndex::new(to.node_index()),

View File

@ -1,6 +1,6 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use crate::layout::primitive::Primitive; use crate::drawing::primitive::Primitive;
#[enum_dispatch] #[enum_dispatch]
pub trait GetConditions { pub trait GetConditions {

View File

@ -1,14 +1,14 @@
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use crate::{ use crate::{
geometry::{GetWidth, SegWeightTrait}, drawing::{
graph::{GenericIndex, GetNodeIndex},
layout::{
graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag}, graph::{GeometryIndex, GeometryWeight, GetLayer, GetNet, MakePrimitive, Retag},
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Drawing,
}, },
geometry::{GetWidth, SegWeightTrait},
graph::{GenericIndex, GetNodeIndex},
}; };
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;

View File

@ -1,10 +1,10 @@
use crate::layout::{ use crate::drawing::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::LooseDotIndex, dot::LooseDotIndex,
graph::GeometryIndex, graph::GeometryIndex,
primitive::{GetInterior, GetJoints, GetOtherJoint, LooseBend, LooseDot}, primitive::{GetInterior, GetJoints, GetOtherJoint, LooseBend, LooseDot},
seg::SeqLooseSegIndex, seg::SeqLooseSegIndex,
Layout, Drawing,
}; };
use super::rules::RulesTrait; use super::rules::RulesTrait;
@ -17,10 +17,10 @@ pub struct Segbend {
} }
impl Segbend { impl Segbend {
pub fn from_dot(dot: LooseDotIndex, layout: &Layout<impl RulesTrait>) -> Self { pub fn from_dot(dot: LooseDotIndex, drawing: &Drawing<impl RulesTrait>) -> Self {
let bend = LooseDot::new(dot, layout).bend(); let bend = LooseDot::new(dot, drawing).bend();
let dot = LooseBend::new(bend, layout).other_joint(dot); let dot = LooseBend::new(bend, drawing).other_joint(dot);
let seg = LooseDot::new(dot, layout).seg().unwrap(); let seg = LooseDot::new(dot, drawing).seg().unwrap();
Self { bend, dot, seg } Self { bend, dot, seg }
} }
} }

View File

@ -4,7 +4,7 @@ use geo::{point, Point, Rotate, Translate};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
layout::{dot::FixedDotWeight, seg::FixedSegWeight, Layout}, drawing::{dot::FixedDotWeight, seg::FixedSegWeight, Drawing},
math::Circle, math::Circle,
}; };
@ -41,9 +41,9 @@ impl DsnDesign {
Ok(Self { pcb }) Ok(Self { pcb })
} }
pub fn make_layout(&self) -> Layout<DsnRules> { pub fn make_drawing(&self) -> Drawing<DsnRules> {
let rules = DsnRules::from_pcb(&self.pcb); let rules = DsnRules::from_pcb(&self.pcb);
let mut layout = Layout::new(rules); let mut layout = Drawing::new(rules);
// mapping of pin id -> net id prepared for adding pins // mapping of pin id -> net id prepared for adding pins
let pin_nets = HashMap::<String, i64>::from_iter( let pin_nets = HashMap::<String, i64>::from_iter(
@ -287,12 +287,12 @@ impl DsnDesign {
} }
fn layer( fn layer(
layout: &Layout<DsnRules>, drawing: &Drawing<DsnRules>,
layer_vec: &Vec<Layer>, layer_vec: &Vec<Layer>,
layer_name: &str, layer_name: &str,
front: bool, front: bool,
) -> usize { ) -> usize {
let image_layer = *layout.rules().layer_ids.get(layer_name).unwrap(); let image_layer = *drawing.rules().layer_ids.get(layer_name).unwrap();
if front { if front {
image_layer as usize image_layer as usize
@ -302,7 +302,7 @@ impl DsnDesign {
} }
fn add_circle( fn add_circle(
layout: &mut Layout<DsnRules>, drawing: &mut Drawing<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -316,13 +316,13 @@ impl DsnDesign {
r, r,
}; };
layout drawing
.add_fixed_dot(FixedDotWeight { circle, layer, net }) .add_fixed_dot(FixedDotWeight { circle, layer, net })
.unwrap(); .unwrap();
} }
fn add_rect( fn add_rect(
layout: &mut Layout<DsnRules>, drawing: &mut Drawing<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -335,7 +335,7 @@ impl DsnDesign {
net: i64, net: i64,
) { ) {
// Corners. // Corners.
let dot_1_1 = layout let dot_1_1 = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x1, y1), pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x1, y1),
@ -345,7 +345,7 @@ impl DsnDesign {
net, net,
}) })
.unwrap(); .unwrap();
let dot_2_1 = layout let dot_2_1 = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x2, y1), pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x2, y1),
@ -355,7 +355,7 @@ impl DsnDesign {
net, net,
}) })
.unwrap(); .unwrap();
let dot_2_2 = layout let dot_2_2 = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x2, y2), pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x2, y2),
@ -365,7 +365,7 @@ impl DsnDesign {
net, net,
}) })
.unwrap(); .unwrap();
let dot_1_2 = layout let dot_1_2 = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x1, y2), pos: Self::pos(place_pos, place_rot, pin_pos, pin_rot, x1, y2),
@ -376,7 +376,7 @@ impl DsnDesign {
}) })
.unwrap(); .unwrap();
// Sides. // Sides.
layout drawing
.add_fixed_seg( .add_fixed_seg(
dot_1_1, dot_1_1,
dot_2_1, dot_2_1,
@ -387,7 +387,7 @@ impl DsnDesign {
}, },
) )
.unwrap(); .unwrap();
layout drawing
.add_fixed_seg( .add_fixed_seg(
dot_2_1, dot_2_1,
dot_2_2, dot_2_2,
@ -398,7 +398,7 @@ impl DsnDesign {
}, },
) )
.unwrap(); .unwrap();
layout drawing
.add_fixed_seg( .add_fixed_seg(
dot_2_2, dot_2_2,
dot_1_2, dot_1_2,
@ -409,7 +409,7 @@ impl DsnDesign {
}, },
) )
.unwrap(); .unwrap();
layout drawing
.add_fixed_seg( .add_fixed_seg(
dot_1_2, dot_1_2,
dot_1_1, dot_1_1,
@ -423,7 +423,7 @@ impl DsnDesign {
} }
fn add_path( fn add_path(
layout: &mut Layout<DsnRules>, drawing: &mut Drawing<DsnRules>,
place_pos: Point, place_pos: Point,
place_rot: f64, place_rot: f64,
pin_pos: Point, pin_pos: Point,
@ -434,7 +434,7 @@ impl DsnDesign {
net: i64, net: i64,
) { ) {
// 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 = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos( pos: Self::pos(
@ -454,7 +454,7 @@ impl DsnDesign {
// iterate through path coords starting from the second // iterate through path coords starting from the second
for coord in coords.iter().skip(1) { for coord in coords.iter().skip(1) {
let index = layout let index = drawing
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
circle: Circle { circle: Circle {
pos: Self::pos( pos: Self::pos(
@ -474,7 +474,7 @@ impl DsnDesign {
.unwrap(); .unwrap();
// add a seg between the current and previous coords // add a seg between the current and previous coords
let _ = layout let _ = drawing
.add_fixed_seg(prev_index, index, FixedSegWeight { width, layer, net }) .add_fixed_seg(prev_index, index, FixedSegWeight { width, layer, net })
.unwrap(); .unwrap();

14
src/dsn/groups.rs Normal file
View File

@ -0,0 +1,14 @@
use petgraph::stable_graph::StableGraph;
use crate::layout::{graph::GeometryIndex, groups::GetGroups};
#[derive(Debug)]
pub struct DsnGroups {
map: BTreeMap<
}
impl GetGroups for DsnGroups {
fn node_groups(&self, node: GeometryIndex) -> Vec<GroupIndex> {
//
}
}

View File

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::layout::rules::{Conditions, RulesTrait}; use crate::drawing::rules::{Conditions, RulesTrait};
use super::structure::Pcb; use super::structure::Pcb;

View File

@ -9,9 +9,7 @@ use petgraph::{
}; };
use crate::{ use crate::{
geometry::shape::{BendShape, DotShape, SegShape, Shape}, drawing::{
graph::{GenericIndex, GetNodeIndex},
layout::{
bend::{BendWeight, FixedBendWeight, LooseBendWeight}, bend::{BendWeight, FixedBendWeight, LooseBendWeight},
dot::{DotWeight, FixedDotWeight, LooseDotWeight}, dot::{DotWeight, FixedDotWeight, LooseDotWeight},
graph::{GeometryWeight, Retag}, graph::{GeometryWeight, Retag},
@ -19,6 +17,8 @@ use crate::{
rules::RulesTrait, rules::RulesTrait,
seg::{FixedSegWeight, LoneLooseSegWeight, SegWeight, SeqLooseSegWeight}, seg::{FixedSegWeight, LoneLooseSegWeight, SegWeight, SeqLooseSegWeight},
}, },
geometry::shape::{BendShape, DotShape, SegShape, Shape},
graph::{GenericIndex, GetNodeIndex},
math::Circle, math::Circle,
}; };

View File

@ -6,8 +6,8 @@ use petgraph::stable_graph::StableDiGraph;
use rstar::{primitives::GeomWithData, RTree, RTreeObject, AABB}; use rstar::{primitives::GeomWithData, RTree, RTreeObject, AABB};
use crate::{ use crate::{
drawing::graph::{GetLayer, Retag},
graph::{GenericIndex, GetNodeIndex}, graph::{GenericIndex, GetNodeIndex},
layout::graph::{GetLayer, Retag},
}; };
use super::{ use super::{

View File

@ -2,8 +2,8 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
drawing::{dot::FixedDotIndex, graph::GetNet, primitive::Primitive, rules::RulesTrait},
graph::GenericIndex, graph::GenericIndex,
layout::{dot::FixedDotIndex, graph::GetNet, primitive::Primitive, rules::RulesTrait},
}; };
pub type ConnectivityGraph = StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>; pub type ConnectivityGraph = StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>;

View File

@ -1,212 +1,64 @@
use contracts::debug_ensures;
use enum_dispatch::enum_dispatch;
use geo::Point; use geo::Point;
use petgraph::stable_graph::StableDiGraph;
use rstar::{RTreeObject, AABB}; use crate::{
use thiserror::Error; drawing::{
bend::LooseBendWeight,
use super::graph::GetLayer; dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight},
use super::loose::{GetNextLoose, Loose, LooseIndex}; rules::RulesTrait,
use super::rules::RulesTrait; seg::{LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, SeqLooseSegWeight},
use super::segbend::Segbend; segbend::Segbend,
use crate::geometry::{ Drawing, Infringement, LayoutException,
shape::{Shape, ShapeTrait},
with_rtree::GeometryWithRtree,
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetOffset, GetPos, GetWidth,
SegWeightTrait,
};
use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::bend::BendIndex;
use crate::layout::collect::Collect;
use crate::layout::dot::DotWeight;
use crate::layout::graph::GetNet;
use crate::layout::guide::Guide;
use crate::layout::primitive::GetLimbs;
use crate::layout::rules::GetConditions;
use crate::layout::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
graph::{GeometryIndex, GeometryWeight, MakePrimitive},
primitive::{GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, MakeShape},
seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SeqLooseSegIndex, SeqLooseSegWeight,
}, },
graph::GetNodeIndex,
wraparoundable::WraparoundableIndex,
}; };
use crate::math::NoTangents;
use crate::wraparoundable::{GetWraparound, Wraparoundable, WraparoundableIndex};
use super::bend::BendWeight; use super::connectivity::{
use super::seg::SegWeight; BandIndex, BandWeight, ConnectivityLabel, ConnectivityWeight, ContinentIndex,
};
#[enum_dispatch]
#[derive(Error, Debug, Clone, Copy)]
pub enum LayoutException {
#[error(transparent)]
NoTangents(#[from] NoTangents),
#[error(transparent)]
Infringement(#[from] Infringement),
#[error(transparent)]
Collision(#[from] Collision),
#[error(transparent)]
AlreadyConnected(#[from] AlreadyConnected),
}
// TODO add real error messages + these should eventually use Display
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} infringes on {1:?}")]
pub struct Infringement(pub Shape, pub GeometryIndex);
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} collides with {1:?}")]
pub struct Collision(pub Shape, pub GeometryIndex);
#[derive(Error, Debug, Clone, Copy)]
#[error("{1:?} is already connected to net {0}")]
pub struct AlreadyConnected(pub i64, pub GeometryIndex);
#[derive(Debug)]
pub struct Layout<R: RulesTrait> { pub struct Layout<R: RulesTrait> {
geometry_with_rtree: GeometryWithRtree< drawing: Drawing<R>, // Shouldn't be public, but is for now because `Draw` needs it.
GeometryWeight, connectivity: StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>,
DotWeight,
SegWeight,
BendWeight,
GeometryIndex,
DotIndex,
SegIndex,
BendIndex,
>,
rules: R,
} }
impl<R: RulesTrait> Layout<R> { impl<R: RulesTrait> Layout<R> {
pub fn new(rules: R) -> Self { pub fn new(drawing: Drawing<R>) -> Self {
Self { Self {
geometry_with_rtree: GeometryWithRtree::new(2), drawing,
rules, connectivity: StableDiGraph::default(),
} }
} }
pub fn remove_band(&mut self, first_loose: SeqLooseSegIndex) { pub fn remove_band(&mut self, band: BandIndex) {
let mut dots = vec![]; todo!()
let mut segs = vec![];
let mut bends = vec![];
let mut outers = vec![];
let mut maybe_loose = Some(first_loose.into());
let mut prev = None;
while let Some(loose) = maybe_loose {
match loose {
LooseIndex::Dot(dot) => {
dots.push(dot);
}
LooseIndex::LoneSeg(seg) => {
self.geometry_with_rtree.remove_seg(seg.into());
break;
}
LooseIndex::SeqSeg(seg) => {
segs.push(seg);
}
LooseIndex::Bend(bend) => {
bends.push(bend);
if let Some(outer) = self.primitive(bend).outer() {
outers.push(outer);
self.reattach_bend(outer, self.primitive(bend).inner());
}
}
}
let prev_prev = prev;
prev = maybe_loose;
maybe_loose = self.loose(loose).next_loose(prev_prev);
}
for bend in bends {
self.geometry_with_rtree.remove_bend(bend.into());
}
for seg in segs {
self.geometry_with_rtree.remove_seg(seg.into());
}
// We must remove the dots only after the segs and bends because we need dots to calculate
// the shapes, which we first need unchanged to remove the segs and bends from the R-tree.
for dot in dots {
self.geometry_with_rtree.remove_dot(dot.into());
}
for outer in outers {
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
}
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 4))]
pub fn remove_segbend(&mut self, segbend: &Segbend, face: LooseDotIndex) { pub fn remove_segbend(&mut self, segbend: &Segbend, face: LooseDotIndex) {
let maybe_outer = self.primitive(segbend.bend).outer(); self.drawing.remove_segbend(segbend, face)
// Removing a loose bend affects its outer bends.
if let Some(outer) = maybe_outer {
self.reattach_bend(outer, self.primitive(segbend.bend).inner());
}
self.geometry_with_rtree.remove_bend(segbend.bend.into());
self.geometry_with_rtree.remove_seg(segbend.seg.into());
// We must remove the dots only after the segs and bends because we need dots to calculate
// the shapes, which we first need unchanged to remove the segs and bends from the R-tree.
self.geometry_with_rtree.remove_dot(face.into());
self.geometry_with_rtree.remove_dot(segbend.dot.into());
if let Some(outer) = maybe_outer {
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
}
} }
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] pub fn start_band(&mut self, from: FixedDotIndex) -> BandIndex {
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] let band = self
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] .connectivity
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> { .add_node(ConnectivityWeight::Band(BandWeight { from, to: None }));
self.add_dot_infringably(weight, None) self.connectivity.update_edge(
self.continent(from.into()).node_index(),
band,
ConnectivityLabel::Band,
);
BandIndex::new(band)
} }
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 1))] pub fn finish_band(&mut self, band: BandIndex, to: FixedDotIndex) {
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] self.connectivity.update_edge(
fn add_dot_infringably<W: DotWeightTrait<GeometryWeight> + GetLayer>( band.node_index(),
&mut self, self.continent(to.into()).node_index(),
weight: W, ConnectivityLabel::Band,
infringables: Option<&[GeometryIndex]>, );
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let dot = self.geometry_with_rtree.add_dot(weight);
self.fail_and_remove_if_infringes_except(dot.into(), infringables)?;
Ok(dot)
} }
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_fixed_seg(
&mut self,
from: FixedDotIndex,
to: FixedDotIndex,
weight: FixedSegWeight,
) -> Result<FixedSegIndex, Infringement> {
self.add_seg_infringably(from.into(), to.into(), weight, None)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn insert_segbend( pub fn insert_segbend(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -216,608 +68,51 @@ impl<R: RulesTrait> Layout<R> {
bend_weight: LooseBendWeight, bend_weight: LooseBendWeight,
cw: bool, cw: bool,
) -> Result<Segbend, LayoutException> { ) -> Result<Segbend, LayoutException> {
let maybe_wraparound = self.wraparoundable(around).wraparound(); self.drawing
let infringables = self.collect().wraparounded_bows(around); .insert_segbend(from, around, dot_weight, seg_weight, bend_weight, cw)
let segbend = self.add_segbend_infringably(
from,
around,
dot_weight,
seg_weight,
bend_weight,
cw,
Some(&infringables),
)?;
if let Some(wraparound) = maybe_wraparound {
self.reattach_bend(wraparound, Some(segbend.bend));
}
if let Some(outer) = self.primitive(segbend.bend).outer() {
self.update_this_and_outward_bows(outer).map_err(|err| {
let joint = self.primitive(segbend.bend).other_joint(segbend.dot);
self.remove_segbend(&segbend, joint.into());
err
})?;
}
// Segs must not cross.
if let Some(collision) = self.detect_collision(segbend.seg.into()) {
let joint = self.primitive(segbend.bend).other_joint(segbend.dot);
self.remove_segbend(&segbend, joint.into());
return Err(collision.into());
}
Ok::<Segbend, LayoutException>(segbend)
} }
#[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())
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() - 1)
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 1))]
fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option<LooseBendIndex>) {
self.geometry_with_rtree
.reattach_bend(bend.into(), maybe_new_inner.map(Into::into));
}
#[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()))]
fn update_this_and_outward_bows(
&mut self,
around: LooseBendIndex,
) -> Result<(), LayoutException> {
// FIXME: Fail gracefully on infringement.
let mut maybe_rail = Some(around);
while let Some(rail) = maybe_rail {
let rail_primitive = self.primitive(rail);
let joints = rail_primitive.joints();
let guide = Guide::new(self);
let from_head = guide.rear_head(joints.1);
let to_head = guide.rear_head(joints.0);
if let Some(inner) = rail_primitive.inner() {
let from = guide
.head_around_bend_segment(
&from_head.into(),
inner.into(),
true,
self.primitive(rail).width(),
)?
.end_point();
let to = guide
.head_around_bend_segment(
&to_head.into(),
inner.into(),
false,
self.primitive(rail).width(),
)?
.end_point();
let offset = guide.head_around_bend_offset(
&from_head.into(),
inner.into(),
self.primitive(rail).width(),
);
self.move_dot_infringably(
joints.0.into(),
from,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.move_dot_infringably(
joints.1.into(),
to,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.shift_bend_infringably(
rail.into(),
offset,
Some(&self.collect().bend_outer_bows(rail)),
)?;
// Update offsets in case the rule conditions changed.
} else {
let core = rail_primitive.core();
let from = guide
.head_around_dot_segment(
&from_head.into(),
core.into(),
true,
self.primitive(rail).width(),
)?
.end_point();
let to = guide
.head_around_dot_segment(
&to_head.into(),
core.into(),
false,
self.primitive(rail).width(),
)?
.end_point();
let offset = guide.head_around_dot_offset(
&from_head.into(),
core.into(),
self.primitive(rail).width(),
);
self.move_dot_infringably(
joints.0.into(),
from,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.move_dot_infringably(
joints.1.into(),
to,
Some(&self.collect().bend_outer_bows(rail)),
)?;
self.shift_bend_infringably(
rail.into(),
offset,
Some(&self.collect().bend_outer_bows(rail)),
)?;
}
maybe_rail = self.primitive(rail).outer();
}
Ok::<(), LayoutException>(())
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_segbend(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
) -> Result<Segbend, LayoutException> {
self.add_segbend_infringably(
from,
around,
dot_weight,
seg_weight,
bend_weight,
cw,
Some(&self.collect().wraparounded_bows(around)),
)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() >= old(self.geometry_with_rtree.graph().edge_count() + 5))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_segbend_infringably(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: SeqLooseSegWeight,
bend_weight: LooseBendWeight,
cw: bool,
infringables: Option<&[GeometryIndex]>,
) -> Result<Segbend, LayoutException> {
let seg_to = self.add_dot_infringably(dot_weight, infringables)?;
let seg = self
.add_seg_infringably(from, seg_to.into(), seg_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
let to = self
.add_dot_infringably(dot_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_seg(seg.into());
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
let (bend_from, bend_to) = if cw { (to, seg_to) } else { (seg_to, to) };
let bend = self
.add_loose_bend_infringably(bend_from, bend_to, around, bend_weight, infringables)
.map_err(|err| {
self.geometry_with_rtree.remove_dot(to.into());
self.geometry_with_rtree.remove_seg(seg.into());
self.geometry_with_rtree.remove_dot(seg_to.into());
err
})?;
Ok::<Segbend, LayoutException>(Segbend {
seg,
dot: seg_to,
bend,
})
}
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_lone_loose_seg( pub fn add_lone_loose_seg(
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
weight: LoneLooseSegWeight, weight: LoneLooseSegWeight,
) -> Result<LoneLooseSegIndex, Infringement> { ) -> Result<LoneLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from.into(), to.into(), weight, Some(&[]))?; self.drawing.add_lone_loose_seg(from, to, weight)
Ok(seg)
} }
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn add_seq_loose_seg( pub fn add_seq_loose_seg(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: LooseDotIndex, to: LooseDotIndex,
weight: SeqLooseSegWeight, weight: SeqLooseSegWeight,
) -> Result<SeqLooseSegIndex, Infringement> { ) -> Result<SeqLooseSegIndex, Infringement> {
let seg = self.add_seg_infringably(from, to.into(), weight, Some(&[]))?; self.drawing.add_seq_loose_seg(from, to, weight)
Ok(seg)
} }
#[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() + 2))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_seg_infringably<W: SegWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let seg = self.geometry_with_rtree.add_seg(from, to, weight);
self.fail_and_remove_if_infringes_except(seg.into(), infringables)?;
Ok(seg)
}
#[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)
|| self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))]
#[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().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_loose_bend_infringably(
&mut self,
from: LooseDotIndex,
to: LooseDotIndex,
around: WraparoundableIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
) -> Result<LooseBendIndex, LayoutException> {
// It makes no sense to wrap something around or under one of its connectables.
//
if weight.net == around.primitive(self).net() {
return Err(AlreadyConnected(weight.net, around.into()).into());
}
//
if let Some(wraparound) = self.wraparoundable(around).wraparound() {
if weight.net == wraparound.primitive(self).net() {
return Err(AlreadyConnected(weight.net, wraparound.into()).into());
}
}
match around {
WraparoundableIndex::FixedDot(core) => self
.add_core_bend_infringably(from.into(), to.into(), core, weight, infringables)
.map_err(Into::into),
WraparoundableIndex::FixedBend(around) => self
.add_outer_bend_infringably(from, to, around.into(), weight, infringables)
.map_err(Into::into),
WraparoundableIndex::LooseBend(around) => self
.add_outer_bend_infringably(from, to, around.into(), weight, infringables)
.map_err(Into::into),
}
}
#[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_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 3))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_core_bend_infringably<W: BendWeightTrait<GeometryWeight> + GetLayer>(
&mut self,
from: DotIndex,
to: DotIndex,
core: FixedDotIndex,
weight: W,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<W>, Infringement>
where
GenericIndex<W>: Into<GeometryIndex> + Copy,
{
let bend = self
.geometry_with_rtree
.add_bend(from, to, core.into(), weight);
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend)
}
#[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_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn add_outer_bend_infringably(
&mut self,
from: LooseDotIndex,
to: LooseDotIndex,
inner: BendIndex,
weight: LooseBendWeight,
infringables: Option<&[GeometryIndex]>,
) -> Result<GenericIndex<LooseBendWeight>, Infringement> {
let core = *self
.geometry_with_rtree
.graph()
.neighbors(inner.node_index())
.filter(|ni| {
matches!(
self.geometry_with_rtree
.graph()
.edge_weight(
self.geometry_with_rtree
.graph()
.find_edge(inner.node_index(), *ni)
.unwrap()
)
.unwrap(),
GeometryLabel::Core
)
})
.map(|ni| FixedDotIndex::new(ni))
.collect::<Vec<FixedDotIndex>>()
.first()
.unwrap();
let bend = self
.geometry_with_rtree
.add_bend(from.into(), to.into(), core.into(), weight);
self.geometry_with_rtree
.reattach_bend(bend.into(), Some(inner));
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend)
}
#[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 flip_bend(&mut self, bend: FixedBendIndex) {
self.geometry_with_rtree.flip_bend(bend.into());
}
pub fn segbend(&self, dot: LooseDotIndex) -> Segbend {
Segbend::from_dot(dot, self)
}
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(ret.is_ok() -> self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
#[debug_ensures(ret.is_err() -> self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count() - 1))]
fn fail_and_remove_if_infringes_except(
&mut self,
node: GeometryIndex,
maybe_except: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
if let Some(infringement) = self.detect_infringement_except(node, maybe_except) {
if let Ok(dot) = node.try_into() {
self.geometry_with_rtree.remove_dot(dot);
} else if let Ok(seg) = node.try_into() {
self.geometry_with_rtree.remove_seg(seg);
} else if let Ok(bend) = node.try_into() {
self.geometry_with_rtree.remove_bend(bend);
}
return Err(infringement);
}
Ok(())
}
pub fn nodes(&self) -> impl Iterator<Item = GeometryIndex> + '_ {
self.geometry_with_rtree
.rtree()
.iter()
.map(|wrapper| wrapper.data)
}
pub fn layer_nodes(&self, layer: u64) -> impl Iterator<Item = GeometryIndex> + '_ {
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&AABB::from_corners(
[-f64::INFINITY, -f64::INFINITY, layer as f64],
[f64::INFINITY, f64::INFINITY, layer as f64],
))
.map(|wrapper| wrapper.data)
}
pub fn node_count(&self) -> usize {
self.geometry_with_rtree.graph().node_count()
}
}
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 move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
match dot { self.drawing.move_dot(dot, to)
DotIndex::Fixed(..) => self.move_dot_infringably(dot, to, Some(&[])),
DotIndex::Loose(..) => self.move_dot_infringably(dot, to, Some(&[])),
}
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] pub fn band_from(&self, band: BandIndex) -> FixedDotIndex {
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] todo!()
fn move_dot_infringably(
&mut self,
dot: DotIndex,
to: Point,
infringables: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
let old_pos = self.geometry_with_rtree.geometry().dot_weight(dot).pos();
self.geometry_with_rtree.move_dot(dot, to);
for limb in dot.primitive(self).limbs() {
if let Some(infringement) = self.detect_infringement_except(limb.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.move_dot(dot, old_pos);
return Err(infringement);
}
}
if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.move_dot(dot, old_pos);
return Err(infringement);
}
Ok(())
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] pub fn band_to(&self, band: BandIndex) -> Option<FixedDotIndex> {
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] todo!()
fn shift_bend_infringably(
&mut self,
bend: BendIndex,
offset: f64,
infringables: Option<&[GeometryIndex]>,
) -> Result<(), Infringement> {
let old_offset = self
.geometry_with_rtree
.geometry()
.bend_weight(bend)
.offset();
self.geometry_with_rtree.shift_bend(bend, offset);
if let Some(infringement) = self.detect_infringement_except(bend.into(), infringables) {
// Restore original state.
self.geometry_with_rtree.shift_bend(bend, old_offset);
return Err(infringement);
}
Ok(())
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] pub fn band_length(&self, band: BandIndex) -> f64 {
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] // TODO.
fn detect_infringement_except( 0.0
&self,
node: GeometryIndex,
maybe_except: Option<&[GeometryIndex]>,
) -> Option<Infringement> {
let limiting_shape = node
.primitive(self)
.shape()
.inflate(self.rules.largest_clearance(node.primitive(self).net()));
let mut inflated_shape = limiting_shape; // Unused temporary value just for initialization.
let conditions = node.primitive(self).conditions();
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&limiting_shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| maybe_except.is_some_and(|except| !except.contains(&wrapper.data)))
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| {
let infringee_conditions = wrapper.data.primitive(self).conditions();
let epsilon = 1.0;
inflated_shape = node.primitive(self).shape().inflate(
(self.rules.clearance(&conditions, &infringee_conditions) - epsilon)
.clamp(0.0, f64::INFINITY),
);
inflated_shape.intersects(&wrapper.data.primitive(self).shape())
})
.map(|wrapper| wrapper.data)
.next()
.and_then(|infringee| Some(Infringement(inflated_shape, infringee)))
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] pub fn layout(&self) -> &Drawing<R> {
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] &self.drawing
fn detect_collision(&self, node: GeometryIndex) -> Option<Collision> {
let shape = node.primitive(self).shape();
self.geometry_with_rtree
.rtree()
.locate_in_envelope_intersecting(&shape.full_height_envelope_3d(0.0, 2))
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
.filter(|wrapper| shape.intersects(&wrapper.data.primitive(self).shape()))
.map(|wrapper| wrapper.data)
.next()
.and_then(|collidee| Some(Collision(shape, collidee)))
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] pub fn continent(&self, dot: FixedDotIndex) -> ContinentIndex {
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] // TODO.
fn are_connectable(&self, node1: GeometryIndex, node2: GeometryIndex) -> bool { ContinentIndex::new(0.into())
let node1_net = node1.primitive(self).net();
let node2_net = node2.primitive(self).net();
(node1_net == node2_net) || node1_net == -1 || node2_net == -2
}
}
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 geometry(
&self,
) -> &Geometry<
GeometryWeight,
DotWeight,
SegWeight,
BendWeight,
GeometryIndex,
DotIndex,
SegIndex,
BendIndex,
> {
self.geometry_with_rtree.geometry()
}
#[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 rules(&self) -> &R {
&self.rules
}
#[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 guide(&self) -> Guide<R> {
Guide::new(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 collect(&self) -> Collect<R> {
Collect::new(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 primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, R> {
GenericPrimitive::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 wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable<R> {
Wraparoundable::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 loose(&self, index: LooseIndex) -> Loose<R> {
Loose::new(index, self)
} }
} }

View File

@ -1,14 +1,4 @@
#[macro_use] pub mod connectivity;
pub mod graph;
pub mod bend;
pub mod collect;
pub mod dot;
pub mod guide;
mod layout; mod layout;
pub mod loose;
pub mod primitive;
pub mod rules;
pub mod seg;
pub mod segbend;
pub use layout::*; pub use layout::*;

View File

@ -4,10 +4,10 @@ pub mod astar;
pub mod draw; pub mod draw;
pub mod graph; pub mod graph;
#[macro_use] #[macro_use]
pub mod layout; pub mod drawing;
pub mod board;
pub mod dsn; pub mod dsn;
pub mod geometry; pub mod geometry;
pub mod layout;
pub mod math; pub mod math;
pub mod mesh; pub mod mesh;
pub mod router; pub mod router;

View File

@ -7,18 +7,18 @@ use petgraph::visit::{self, NodeIndexable};
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef}; use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
use spade::{HasPosition, InsertionError, Point2}; use spade::{HasPosition, InsertionError, Point2};
use crate::layout::rules::RulesTrait; use crate::drawing::rules::RulesTrait;
use crate::triangulation::TriangulationEdgeReference; use crate::triangulation::TriangulationEdgeReference;
use crate::{ use crate::{
geometry::shape::ShapeTrait, drawing::{
graph::GetNodeIndex,
layout::{
bend::{FixedBendIndex, LooseBendIndex}, bend::{FixedBendIndex, LooseBendIndex},
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::{GetCore, MakeShape, Primitive}, primitive::{GetCore, MakeShape, Primitive},
Layout, Drawing,
}, },
geometry::shape::ShapeTrait,
graph::GetNodeIndex,
triangulation::{GetVertexIndex, Triangulation}, triangulation::{GetVertexIndex, Triangulation},
}; };
@ -83,7 +83,7 @@ pub struct Mesh {
} }
impl Mesh { impl Mesh {
pub fn new(layout: &Layout<impl RulesTrait>) -> Self { pub fn new(layout: &Drawing<impl RulesTrait>) -> Self {
let mut this = Self { let mut this = Self {
triangulation: Triangulation::new(layout), triangulation: Triangulation::new(layout),
vertex_to_triangulation_vertex: Vec::new(), vertex_to_triangulation_vertex: Vec::new(),
@ -93,9 +93,9 @@ impl Mesh {
this this
} }
pub fn generate(&mut self, layout: &Layout<impl RulesTrait>) -> Result<(), InsertionError> { pub fn generate(&mut self, drawing: &Drawing<impl RulesTrait>) -> Result<(), InsertionError> {
for node in layout.nodes() { for node in drawing.nodes() {
let center = node.primitive(layout).shape().center(); let center = node.primitive(drawing).shape().center();
match node { match node {
GeometryIndex::FixedDot(dot) => { GeometryIndex::FixedDot(dot) => {
@ -116,16 +116,16 @@ impl Mesh {
} }
} }
for node in layout.nodes() { for node in drawing.nodes() {
// Add rails as vertices. This is how the mesh differs from the triangulation. // Add rails as vertices. This is how the mesh differs from the triangulation.
match node { match node {
GeometryIndex::LooseBend(bend) => { GeometryIndex::LooseBend(bend) => {
self.triangulation self.triangulation
.weight_mut(layout.primitive(bend).core().into()) .weight_mut(drawing.primitive(bend).core().into())
.rails .rails
.push(bend.into()); .push(bend.into());
self.vertex_to_triangulation_vertex[bend.node_index().index()] = self.vertex_to_triangulation_vertex[bend.node_index().index()] =
Some(layout.primitive(bend).core().into()); Some(drawing.primitive(bend).core().into());
} }
_ => (), _ => (),
} }

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; use crate::drawing::{
use crate::layout::{
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::MakeShape, primitive::MakeShape,
rules::RulesTrait, rules::RulesTrait,
}; };
use crate::geometry::shape::ShapeTrait;
use crate::layout::connectivity::BandIndex;
use crate::layout::Layout;
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
@ -52,7 +52,7 @@ pub trait RouterObserverTrait<R: RulesTrait> {
} }
pub struct Router<R: RulesTrait> { pub struct Router<R: RulesTrait> {
pub board: Board<R>, pub layout: Layout<R>,
} }
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> { struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
@ -99,14 +99,14 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
return None; return None;
} }
let before_probe_length = self.tracer.board.band_length(self.trace.band); let before_probe_length = self.tracer.layout.band_length(self.trace.band);
let width = self.trace.width; let width = self.trace.width;
let result = self.tracer.step(&mut self.trace, edge.target(), width); let result = self.tracer.step(&mut self.trace, edge.target(), 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.board.band_length(self.trace.band); let probe_length = self.tracer.layout.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);
@ -119,12 +119,12 @@ 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.board.layout()) .primitive(self.tracer.layout.layout())
.shape() .shape()
.center(); .center();
let end_point = self let end_point = self
.tracer .tracer
.board .layout
.layout() .layout()
.primitive(self.to) .primitive(self.to)
.shape() .shape()
@ -134,8 +134,8 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
} }
impl<R: RulesTrait> Router<R> { impl<R: RulesTrait> Router<R> {
pub fn new(board: Board<R>) -> Self { pub fn new(layout: Layout<R>) -> Self {
Router { board } Router { layout }
} }
pub fn route_band( pub fn route_band(
@ -148,8 +148,8 @@ 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.board.layout()); let mut mesh = Mesh::new(self.layout.layout());
mesh.generate(self.board.layout()) mesh.generate(self.layout.layout())
.map_err(|err| RoutingError { .map_err(|err| RoutingError {
from, from,
to, to,
@ -181,14 +181,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.board.band_from(band); let from_dot = self.layout.band_from(band);
let to_dot = self.board.band_to(band).unwrap(); let to_dot = self.layout.band_to(band).unwrap();
self.board.remove_band(band); self.layout.remove_band(band);
self.board.move_dot(to_dot.into(), to).unwrap(); // TODO: Remove `.unwrap()`. self.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.board, mesh) Tracer::new(&mut self.layout, mesh)
} }
} }

View File

@ -1,15 +1,15 @@
use contracts::debug_ensures; use contracts::debug_ensures;
use crate::{ use crate::{
board::{connectivity::BandIndex, Board},
draw::{Draw, DrawException}, draw::{Draw, DrawException},
layout::{ drawing::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GetNet, MakePrimitive}, graph::{GetNet, MakePrimitive},
guide::{BareHead, Head, HeadTrait, SegbendHead}, guide::{BareHead, Head, HeadTrait, SegbendHead},
rules::RulesTrait, rules::RulesTrait,
}, },
layout::{connectivity::BandIndex, Layout},
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
}; };
@ -22,17 +22,17 @@ pub struct Trace {
} }
pub struct Tracer<'a, R: RulesTrait> { pub struct Tracer<'a, R: RulesTrait> {
pub board: &'a mut Board<R>, pub layout: &'a mut Layout<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(board: &'a mut Board<R>, mesh: &'a Mesh) -> Self { pub fn new(layout: &'a mut Layout<R>, mesh: &'a Mesh) -> Self {
Tracer { board, mesh } Tracer { layout, mesh }
} }
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {
let band = self.board.start_band(from); let band = self.layout.start_band(from);
Trace { Trace {
path: vec![from.into()], path: vec![from.into()],
head: BareHead { dot: from }.into(), head: BareHead { dot: from }.into(),
@ -48,7 +48,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
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)) Ok(self.layout.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())]
@ -158,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.board) Draw::new(&mut self.layout)
} }
} }

View File

@ -5,8 +5,8 @@ use petgraph::visit::{self, NodeIndexable};
use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError}; use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError};
use crate::{ use crate::{
drawing::{rules::RulesTrait, Drawing},
graph::GetNodeIndex, graph::GetNodeIndex,
layout::{rules::RulesTrait, Layout},
}; };
pub trait GetVertexIndex<I> { pub trait GetVertexIndex<I> {
@ -23,7 +23,7 @@ pub struct Triangulation<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>> impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
Triangulation<I, W> Triangulation<I, W>
{ {
pub fn new(layout: &Layout<impl RulesTrait>) -> Self { pub fn new(layout: &Drawing<impl RulesTrait>) -> Self {
let mut this = Self { let mut this = Self {
triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(), triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(),
vertex_to_handle: Vec::new(), vertex_to_handle: Vec::new(),

View File

@ -2,15 +2,15 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
graph::GetNodeIndex, drawing::{
layout::{
bend::{BendIndex, FixedBendIndex, LooseBendIndex}, bend::{BendIndex, FixedBendIndex, LooseBendIndex},
dot::FixedDotIndex, dot::FixedDotIndex,
graph::{GeometryIndex, MakePrimitive}, graph::{GeometryIndex, MakePrimitive},
primitive::{FixedBend, FixedDot, GetFirstRail, GetInnerOuter, LooseBend, Primitive}, primitive::{FixedBend, FixedDot, GetFirstRail, GetInnerOuter, LooseBend, Primitive},
rules::RulesTrait, rules::RulesTrait,
Layout, Drawing,
}, },
graph::GetNodeIndex,
}; };
#[enum_dispatch] #[enum_dispatch]
@ -53,11 +53,11 @@ pub enum Wraparoundable<'a, R: RulesTrait> {
} }
impl<'a, R: RulesTrait> Wraparoundable<'a, R> { impl<'a, R: RulesTrait> Wraparoundable<'a, R> {
pub fn new(index: WraparoundableIndex, layout: &'a Layout<R>) -> Self { pub fn new(index: WraparoundableIndex, drawing: &'a Drawing<R>) -> Self {
match index { match index {
WraparoundableIndex::FixedDot(dot) => layout.primitive(dot).into(), WraparoundableIndex::FixedDot(dot) => drawing.primitive(dot).into(),
WraparoundableIndex::FixedBend(bend) => layout.primitive(bend).into(), WraparoundableIndex::FixedBend(bend) => drawing.primitive(bend).into(),
WraparoundableIndex::LooseBend(bend) => layout.primitive(bend).into(), WraparoundableIndex::LooseBend(bend) => drawing.primitive(bend).into(),
} }
} }
} }