mirror of https://codeberg.org/topola/topola.git
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:
parent
765738f44b
commit
91f9466d74
|
|
@ -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<usize>,
|
||||
edge_indices: Peekable<EdgeIndices<usize>>,
|
||||
navmesh: Navmesh, // Useful for debugging.
|
||||
}
|
||||
|
||||
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>(
|
||||
&mut self,
|
||||
autorouter: &mut Autorouter<R>,
|
||||
|
|
@ -29,11 +50,33 @@ 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, 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(to_dot, 100.0, observer);
|
||||
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
|
||||
|
|
@ -57,17 +100,12 @@ impl Autoroute {
|
|||
RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone),
|
||||
};
|
||||
|
||||
(navmesh, from_dot, to_dot)
|
||||
};
|
||||
(from_dot, to_dot)
|
||||
}
|
||||
|
||||
let router = Router::new_with_navmesh(
|
||||
&mut autorouter.layout,
|
||||
std::mem::replace(&mut self.navmesh, navmesh),
|
||||
);
|
||||
router
|
||||
.unwrap()
|
||||
.route_band(from_dot, to_dot, 100.0, observer);
|
||||
Some(())
|
||||
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 {
|
||||
|
|
@ -86,18 +124,16 @@ impl<R: RulesTrait> Autorouter<R> {
|
|||
Ok(Self { ratsnest, layout })
|
||||
}
|
||||
|
||||
pub fn autoroute(&mut self, observer: &mut impl RouterObserverTrait<R>) {
|
||||
let mut it = self.autoroute_iter();
|
||||
pub fn autoroute(&mut self, layer: u64, observer: &mut impl RouterObserverTrait<R>) {
|
||||
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> {
|
||||
Autoroute::new(self.ratsnest.graph().edge_indices(), self)
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> {
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ impl eframe::App for App {
|
|||
|
||||
execute(async move {
|
||||
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(
|
||||
|
|
@ -208,7 +208,9 @@ impl eframe::App for App {
|
|||
shared_data: shared_data.clone(),
|
||||
},
|
||||
) {
|
||||
shared_data.lock().unwrap().navmesh = Some(it.navmesh().clone());
|
||||
shared_data.lock().unwrap().navmesh =
|
||||
Some(it.navmesh().clone());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ pub struct 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 {
|
||||
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) => {
|
||||
|
|
|
|||
|
|
@ -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<R: RulesTrait> {
|
|||
|
||||
pub struct Router<'a, R: RulesTrait> {
|
||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
||||
from: FixedDotIndex,
|
||||
navmesh: Navmesh,
|
||||
}
|
||||
|
||||
|
|
@ -143,37 +145,48 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64>
|
|||
}
|
||||
|
||||
impl<'a, R: RulesTrait> Router<'a, R> {
|
||||
pub fn new(layout: &'a mut Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> {
|
||||
let navmesh = Navmesh::new(&layout.lock().unwrap())?;
|
||||
Self::new_with_navmesh(layout, navmesh)
|
||||
pub fn new(
|
||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
||||
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(
|
||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
||||
from: FixedDotIndex,
|
||||
navmesh: Navmesh,
|
||||
) -> Result<Self, InsertionError> {
|
||||
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<R>,
|
||||
) -> Result<BandIndex, RoutingError> {
|
||||
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<R> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue