From 91f9466d74b63b21bd775773b0a18e8cd96ba39a Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Tue, 7 May 2024 20:01:18 +0200 Subject: [PATCH] autorouter,router: route only single layer at a time It makes no sense to route multiple layers at once until we implement automatic via placement, which is going to take a lot of time. --- src/autorouter/autorouter.rs | 118 +++++++++++++++++++++++------------ src/bin/topola-egui/app.rs | 20 +++--- src/router/navmesh.rs | 6 +- src/router/router.rs | 31 ++++++--- 4 files changed, 113 insertions(+), 62 deletions(-) diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 9cd82c7..43b8d4d 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -1,26 +1,47 @@ -use std::sync::{Arc, Mutex}; +use std::{ + iter::Peekable, + sync::{Arc, Mutex}, +}; use geo::Point; use petgraph::{ - graph::EdgeIndices, + graph::{EdgeIndex, EdgeIndices, NodeIndex}, visit::{EdgeRef, IntoEdgeReferences}, }; use spade::InsertionError; use crate::{ autorouter::ratsnest::{Ratsnest, RatsnestVertexIndex}, - drawing::{dot::FixedDotIndex, rules::RulesTrait}, + drawing::{dot::FixedDotIndex, graph::GetLayer, rules::RulesTrait}, layout::{connectivity::BandIndex, Layout}, router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError}, triangulation::GetVertexIndex, }; pub struct Autoroute { - edge_indices: EdgeIndices, + edge_indices: Peekable>, navmesh: Navmesh, // Useful for debugging. } impl Autoroute { + pub fn new( + edge_indices: EdgeIndices, + autorouter: &mut Autorouter, + ) -> Option { + let mut peekable_edge_indices = edge_indices.peekable(); + let Some(ratline) = peekable_edge_indices.peek() else { + return None; + }; + + let mut layout = autorouter.layout.lock().unwrap(); + let (from_dot, to_dot) = Self::terminating_dots(autorouter, &mut layout, ratline); + let navmesh = Self::next_navmesh(&layout, from_dot); + Some(Self { + edge_indices: peekable_edge_indices, + navmesh, + }) + } + pub fn next( &mut self, autorouter: &mut Autorouter, @@ -29,47 +50,64 @@ impl Autoroute { let Some(ratline) = self.edge_indices.next() else { return None; }; - let (from, to) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap(); let (navmesh, from_dot, to_dot) = { let mut layout = autorouter.layout.lock().unwrap(); - let navmesh = Navmesh::new(&layout).unwrap(); - - let from_dot = match autorouter - .ratsnest - .graph() - .node_weight(from) - .unwrap() - .vertex_index() - { - RatsnestVertexIndex::FixedDot(dot) => dot, - RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone), - }; - - let to_dot = match autorouter - .ratsnest - .graph() - .node_weight(to) - .unwrap() - .vertex_index() - { - RatsnestVertexIndex::FixedDot(dot) => dot, - RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone), - }; - + let (from_dot, to_dot) = Self::terminating_dots(autorouter, &mut layout, &ratline); + let navmesh = Self::next_navmesh(&layout, from_dot); (navmesh, from_dot, to_dot) }; let router = Router::new_with_navmesh( &mut autorouter.layout, + from_dot, std::mem::replace(&mut self.navmesh, navmesh), ); - router - .unwrap() - .route_band(from_dot, to_dot, 100.0, observer); + router.unwrap().route_band(to_dot, 100.0, observer); Some(()) } + fn terminating_dots( + autorouter: &Autorouter, + layout: &mut Layout, + ratline: &EdgeIndex, + ) -> (FixedDotIndex, FixedDotIndex) { + let (from, to) = autorouter + .ratsnest + .graph() + .edge_endpoints(*ratline) + .unwrap(); + + let from_dot = match autorouter + .ratsnest + .graph() + .node_weight(from) + .unwrap() + .vertex_index() + { + RatsnestVertexIndex::FixedDot(dot) => dot, + RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone), + }; + + let to_dot = match autorouter + .ratsnest + .graph() + .node_weight(to) + .unwrap() + .vertex_index() + { + RatsnestVertexIndex::FixedDot(dot) => dot, + RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone), + }; + + (from_dot, to_dot) + } + + fn next_navmesh(layout: &Layout, from: FixedDotIndex) -> Navmesh { + let layer = layout.drawing().primitive(from).layer(); + Navmesh::new(layout, layer).unwrap() + } + pub fn navmesh(&self) -> &Navmesh { &self.navmesh } @@ -86,18 +124,16 @@ impl Autorouter { Ok(Self { ratsnest, layout }) } - pub fn autoroute(&mut self, observer: &mut impl RouterObserverTrait) { - let mut it = self.autoroute_iter(); - while let Some(()) = it.next(self, observer) { - // + pub fn autoroute(&mut self, layer: u64, observer: &mut impl RouterObserverTrait) { + if let Some(mut it) = self.autoroute_iter() { + while let Some(()) = it.next(self, observer) { + // + } } } - pub fn autoroute_iter(&mut self) -> Autoroute { - Autoroute { - edge_indices: self.ratsnest.graph().edge_indices(), - navmesh: Navmesh::new(&self.layout.lock().unwrap()).unwrap(), - } + pub fn autoroute_iter(&mut self) -> Option { + Autoroute::new(self.ratsnest.graph().edge_indices(), self) } pub fn layout(&self) -> &Arc>> { diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 78c44ec..fb75efa 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -199,16 +199,18 @@ impl eframe::App for App { execute(async move { let mut autorouter = Autorouter::new(layout).unwrap(); - let mut it = autorouter.autoroute_iter(); - shared_data.lock().unwrap().navmesh = Some(it.navmesh().clone()); - - while let Some(()) = it.next( - &mut autorouter, - &mut DebugRouterObserver { - shared_data: shared_data.clone(), - }, - ) { + if let Some(mut it) = autorouter.autoroute_iter() { shared_data.lock().unwrap().navmesh = Some(it.navmesh().clone()); + + while let Some(()) = it.next( + &mut autorouter, + &mut DebugRouterObserver { + shared_data: shared_data.clone(), + }, + ) { + shared_data.lock().unwrap().navmesh = + Some(it.navmesh().clone()); + } } }); } diff --git a/src/router/navmesh.rs b/src/router/navmesh.rs index cf3c4de..a43659a 100644 --- a/src/router/navmesh.rs +++ b/src/router/navmesh.rs @@ -83,7 +83,7 @@ pub struct Navmesh { } impl Navmesh { - pub fn new(layout: &Layout) -> Result { + pub fn new(layout: &Layout, layer: u64) -> Result { let mut this = Self { triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()), vertex_to_triangulation_vertex: Vec::new(), @@ -91,7 +91,7 @@ impl Navmesh { this.vertex_to_triangulation_vertex .resize(layout.drawing().geometry().graph().node_bound(), None); - for node in layout.drawing().primitive_nodes() { + for node in layout.drawing().layer_primitive_nodes(layer) { let center = node.primitive(layout.drawing()).shape().center(); match node { @@ -113,7 +113,7 @@ impl Navmesh { } } - for node in layout.drawing().primitive_nodes() { + for node in layout.drawing().layer_primitive_nodes(layer) { // Add rails as vertices. This is how the navmesh differs from the triangulation. match node { PrimitiveIndex::LooseBend(bend) => { diff --git a/src/router/router.rs b/src/router/router.rs index edc4e6b..567f080 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -6,6 +6,7 @@ use petgraph::visit::EdgeRef; use spade::InsertionError; use thiserror::Error; +use crate::drawing::graph::GetLayer; use crate::geometry::primitive::PrimitiveShapeTrait; use crate::layout::connectivity::BandIndex; use crate::layout::Layout; @@ -59,6 +60,7 @@ pub trait RouterObserverTrait { pub struct Router<'a, R: RulesTrait> { layout: &'a mut Arc>>, + from: FixedDotIndex, navmesh: Navmesh, } @@ -143,37 +145,48 @@ impl<'a, RO: RouterObserverTrait, R: RulesTrait> AstarStrategy<&Navmesh, f64> } impl<'a, R: RulesTrait> Router<'a, R> { - pub fn new(layout: &'a mut Arc>>) -> Result { - let navmesh = Navmesh::new(&layout.lock().unwrap())?; - Self::new_with_navmesh(layout, navmesh) + pub fn new( + layout: &'a mut Arc>>, + from: FixedDotIndex, + ) -> Result { + let navmesh = { + let layout = layout.lock().unwrap(); + let layer = layout.drawing().primitive(from).layer(); + Navmesh::new(&layout, layer)? + }; + Self::new_with_navmesh(layout, from, navmesh) } pub fn new_with_navmesh( layout: &'a mut Arc>>, + from: FixedDotIndex, navmesh: Navmesh, ) -> Result { - Ok(Self { layout, navmesh }) + Ok(Self { + layout, + from, + navmesh, + }) } pub fn route_band( &mut self, - from: FixedDotIndex, to: FixedDotIndex, width: f64, observer: &mut impl RouterObserverTrait, ) -> Result { let mut tracer = self.tracer(); - let trace = tracer.start(from, width); + let trace = tracer.start(self.from, width); let band = trace.band; let (_cost, _path) = astar( &self.navmesh, - from.into(), + self.from.into(), &mut RouterAstarStrategy::new(tracer, trace, to.into(), observer), ) .ok_or(RoutingError { - from, + from: self.from, to, source: RoutingErrorKind::AStar, })?; @@ -198,7 +211,7 @@ impl<'a, R: RulesTrait> Router<'a, R> { (from_dot, to_dot) }; - self.route_band(from_dot, to_dot, width, observer) + self.route_band(to_dot, width, observer) } fn tracer(&mut self) -> Tracer {