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.
This commit is contained in:
Mikolaj Wielgus 2024-05-07 20:01:18 +02:00
parent 765738f44b
commit 91f9466d74
4 changed files with 113 additions and 62 deletions

View File

@ -1,26 +1,47 @@
use std::sync::{Arc, Mutex}; use std::{
iter::Peekable,
sync::{Arc, Mutex},
};
use geo::Point; use geo::Point;
use petgraph::{ use petgraph::{
graph::EdgeIndices, graph::{EdgeIndex, EdgeIndices, NodeIndex},
visit::{EdgeRef, IntoEdgeReferences}, visit::{EdgeRef, IntoEdgeReferences},
}; };
use spade::InsertionError; use spade::InsertionError;
use crate::{ use crate::{
autorouter::ratsnest::{Ratsnest, RatsnestVertexIndex}, autorouter::ratsnest::{Ratsnest, RatsnestVertexIndex},
drawing::{dot::FixedDotIndex, rules::RulesTrait}, drawing::{dot::FixedDotIndex, graph::GetLayer, rules::RulesTrait},
layout::{connectivity::BandIndex, Layout}, layout::{connectivity::BandIndex, Layout},
router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError}, router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError},
triangulation::GetVertexIndex, triangulation::GetVertexIndex,
}; };
pub struct Autoroute { pub struct Autoroute {
edge_indices: EdgeIndices<usize>, edge_indices: Peekable<EdgeIndices<usize>>,
navmesh: Navmesh, // Useful for debugging. navmesh: Navmesh, // Useful for debugging.
} }
impl Autoroute { impl Autoroute {
pub fn new(
edge_indices: EdgeIndices<usize>,
autorouter: &mut Autorouter<impl RulesTrait>,
) -> Option<Self> {
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<R: RulesTrait>( pub fn next<R: RulesTrait>(
&mut self, &mut self,
autorouter: &mut Autorouter<R>, autorouter: &mut Autorouter<R>,
@ -29,47 +50,64 @@ impl Autoroute {
let Some(ratline) = self.edge_indices.next() else { let Some(ratline) = self.edge_indices.next() else {
return None; return None;
}; };
let (from, to) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap();
let (navmesh, from_dot, to_dot) = { let (navmesh, from_dot, to_dot) = {
let mut layout = autorouter.layout.lock().unwrap(); let mut layout = autorouter.layout.lock().unwrap();
let navmesh = Navmesh::new(&layout).unwrap(); let (from_dot, to_dot) = Self::terminating_dots(autorouter, &mut layout, &ratline);
let navmesh = Self::next_navmesh(&layout, from_dot);
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),
};
(navmesh, from_dot, to_dot) (navmesh, from_dot, to_dot)
}; };
let router = Router::new_with_navmesh( let router = Router::new_with_navmesh(
&mut autorouter.layout, &mut autorouter.layout,
from_dot,
std::mem::replace(&mut self.navmesh, navmesh), std::mem::replace(&mut self.navmesh, navmesh),
); );
router router.unwrap().route_band(to_dot, 100.0, observer);
.unwrap()
.route_band(from_dot, to_dot, 100.0, observer);
Some(()) Some(())
} }
fn terminating_dots<R: RulesTrait>(
autorouter: &Autorouter<R>,
layout: &mut Layout<R>,
ratline: &EdgeIndex<usize>,
) -> (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<impl RulesTrait>, from: FixedDotIndex) -> Navmesh {
let layer = layout.drawing().primitive(from).layer();
Navmesh::new(layout, layer).unwrap()
}
pub fn navmesh(&self) -> &Navmesh { pub fn navmesh(&self) -> &Navmesh {
&self.navmesh &self.navmesh
} }
@ -86,18 +124,16 @@ impl<R: RulesTrait> Autorouter<R> {
Ok(Self { ratsnest, layout }) Ok(Self { ratsnest, layout })
} }
pub fn autoroute(&mut self, observer: &mut impl RouterObserverTrait<R>) { pub fn autoroute(&mut self, layer: u64, observer: &mut impl RouterObserverTrait<R>) {
let mut it = self.autoroute_iter(); if let Some(mut it) = self.autoroute_iter() {
while let Some(()) = it.next(self, observer) { while let Some(()) = it.next(self, observer) {
// //
}
} }
} }
pub fn autoroute_iter(&mut self) -> Autoroute { pub fn autoroute_iter(&mut self) -> Option<Autoroute> {
Autoroute { Autoroute::new(self.ratsnest.graph().edge_indices(), self)
edge_indices: self.ratsnest.graph().edge_indices(),
navmesh: Navmesh::new(&self.layout.lock().unwrap()).unwrap(),
}
} }
pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> { pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> {

View File

@ -199,16 +199,18 @@ impl eframe::App for App {
execute(async move { execute(async move {
let mut autorouter = Autorouter::new(layout).unwrap(); let mut autorouter = Autorouter::new(layout).unwrap();
let mut it = autorouter.autoroute_iter(); 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()); 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());
}
} }
}); });
} }

View File

@ -83,7 +83,7 @@ pub struct Navmesh {
} }
impl Navmesh { impl Navmesh {
pub fn new(layout: &Layout<impl RulesTrait>) -> Result<Self, InsertionError> { pub fn new(layout: &Layout<impl RulesTrait>, layer: u64) -> Result<Self, InsertionError> {
let mut this = Self { let mut this = Self {
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()), triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
vertex_to_triangulation_vertex: Vec::new(), vertex_to_triangulation_vertex: Vec::new(),
@ -91,7 +91,7 @@ impl Navmesh {
this.vertex_to_triangulation_vertex this.vertex_to_triangulation_vertex
.resize(layout.drawing().geometry().graph().node_bound(), None); .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(); let center = node.primitive(layout.drawing()).shape().center();
match node { 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. // Add rails as vertices. This is how the navmesh differs from the triangulation.
match node { match node {
PrimitiveIndex::LooseBend(bend) => { PrimitiveIndex::LooseBend(bend) => {

View File

@ -6,6 +6,7 @@ use petgraph::visit::EdgeRef;
use spade::InsertionError; use spade::InsertionError;
use thiserror::Error; use thiserror::Error;
use crate::drawing::graph::GetLayer;
use crate::geometry::primitive::PrimitiveShapeTrait; use crate::geometry::primitive::PrimitiveShapeTrait;
use crate::layout::connectivity::BandIndex; use crate::layout::connectivity::BandIndex;
use crate::layout::Layout; use crate::layout::Layout;
@ -59,6 +60,7 @@ pub trait RouterObserverTrait<R: RulesTrait> {
pub struct Router<'a, R: RulesTrait> { pub struct Router<'a, R: RulesTrait> {
layout: &'a mut Arc<Mutex<Layout<R>>>, layout: &'a mut Arc<Mutex<Layout<R>>>,
from: FixedDotIndex,
navmesh: Navmesh, navmesh: Navmesh,
} }
@ -143,37 +145,48 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64>
} }
impl<'a, R: RulesTrait> Router<'a, R> { impl<'a, R: RulesTrait> Router<'a, R> {
pub fn new(layout: &'a mut Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> { pub fn new(
let navmesh = Navmesh::new(&layout.lock().unwrap())?; layout: &'a mut Arc<Mutex<Layout<R>>>,
Self::new_with_navmesh(layout, navmesh) from: FixedDotIndex,
) -> Result<Self, InsertionError> {
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( pub fn new_with_navmesh(
layout: &'a mut Arc<Mutex<Layout<R>>>, layout: &'a mut Arc<Mutex<Layout<R>>>,
from: FixedDotIndex,
navmesh: Navmesh, navmesh: Navmesh,
) -> Result<Self, InsertionError> { ) -> Result<Self, InsertionError> {
Ok(Self { layout, navmesh }) Ok(Self {
layout,
from,
navmesh,
})
} }
pub fn route_band( pub fn route_band(
&mut self, &mut self,
from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
width: f64, width: f64,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> { ) -> Result<BandIndex, RoutingError> {
let mut tracer = self.tracer(); let mut tracer = self.tracer();
let trace = tracer.start(from, width); let trace = tracer.start(self.from, width);
let band = trace.band; let band = trace.band;
let (_cost, _path) = astar( let (_cost, _path) = astar(
&self.navmesh, &self.navmesh,
from.into(), self.from.into(),
&mut RouterAstarStrategy::new(tracer, trace, to.into(), observer), &mut RouterAstarStrategy::new(tracer, trace, to.into(), observer),
) )
.ok_or(RoutingError { .ok_or(RoutingError {
from, from: self.from,
to, to,
source: RoutingErrorKind::AStar, source: RoutingErrorKind::AStar,
})?; })?;
@ -198,7 +211,7 @@ impl<'a, R: RulesTrait> Router<'a, R> {
(from_dot, to_dot) (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<R> { fn tracer(&mut self) -> Tracer<R> {