autorouter: autoroute only selected

This commit is contained in:
Mikolaj Wielgus 2024-05-12 20:29:07 +02:00
parent a6fb1157e3
commit f893f73cd8
3 changed files with 55 additions and 13 deletions

View File

@ -1,11 +1,12 @@
use std::{ use std::{
collections::HashSet,
iter::Peekable, iter::Peekable,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use geo::Point; use geo::Point;
use petgraph::{ use petgraph::{
graph::{EdgeIndex, EdgeIndices, NodeIndex}, graph::{EdgeIndex, EdgeIndices},
visit::{EdgeRef, IntoEdgeReferences}, visit::{EdgeRef, IntoEdgeReferences},
}; };
use spade::InsertionError; use spade::InsertionError;
@ -17,22 +18,24 @@ use crate::{
graph::{GetLayer, GetMaybeNet}, graph::{GetLayer, GetMaybeNet},
rules::RulesTrait, rules::RulesTrait,
}, },
layout::{connectivity::BandIndex, Layout}, layout::{connectivity::BandIndex, Layout, NodeIndex},
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>, ratlines_iter: Box<dyn Iterator<Item = EdgeIndex<usize>>>,
navmesh: Option<Navmesh>, // Useful for debugging. navmesh: Option<Navmesh>, // Useful for debugging.
} }
impl Autoroute { impl Autoroute {
pub fn new( pub fn new(
mut edge_indices: EdgeIndices<usize>, ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
autorouter: &mut Autorouter<impl RulesTrait>, autorouter: &mut Autorouter<impl RulesTrait>,
) -> Option<Self> { ) -> Option<Self> {
let Some(cur_edge) = edge_indices.next() else { let mut ratlines_iter = Box::new(ratlines.into_iter());
let Some(cur_edge) = ratlines_iter.next() else {
return None; return None;
}; };
@ -41,7 +44,7 @@ impl Autoroute {
let navmesh = Some(Navmesh::new(&layout, from, to).ok()?); let navmesh = Some(Navmesh::new(&layout, from, to).ok()?);
let this = Self { let this = Self {
edge_indices, ratlines_iter,
navmesh, navmesh,
}; };
@ -53,7 +56,7 @@ impl Autoroute {
autorouter: &mut Autorouter<R>, autorouter: &mut Autorouter<R>,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<R>,
) -> bool { ) -> bool {
let new_navmesh = if let Some(cur_edge) = self.edge_indices.next() { let new_navmesh = if let Some(cur_edge) = self.ratlines_iter.next() {
let (from, to) = Self::edge_from_to(autorouter, cur_edge); let (from, to) = Self::edge_from_to(autorouter, cur_edge);
let layout = autorouter.layout.lock().unwrap(); let layout = autorouter.layout.lock().unwrap();
@ -119,16 +122,44 @@ impl<R: RulesTrait> Autorouter<R> {
Ok(Self { layout, ratsnest }) Ok(Self { layout, ratsnest })
} }
pub fn autoroute(&mut self, layer: u64, observer: &mut impl RouterObserverTrait<R>) { pub fn autoroute(
if let Some(mut autoroute) = self.autoroute_walk() { &mut self,
selection: &HashSet<NodeIndex>,
observer: &mut impl RouterObserverTrait<R>,
) {
if let Some(mut autoroute) = self.autoroute_walk(selection) {
while autoroute.next(self, observer) { while autoroute.next(self, observer) {
// //
} }
} }
} }
pub fn autoroute_walk(&mut self) -> Option<Autoroute> { pub fn autoroute_walk(&mut self, selection: &HashSet<NodeIndex>) -> Option<Autoroute> {
Autoroute::new(self.ratsnest.graph().edge_indices(), self) Autoroute::new(
self.ratsnest
.graph()
.edge_indices()
.filter(|edge| {
let (from, to) = self.ratsnest.graph().edge_endpoints(*edge).unwrap();
let from_vertex = self
.ratsnest
.graph()
.node_weight(from)
.unwrap()
.vertex_index();
let to_vertex = self
.ratsnest
.graph()
.node_weight(to)
.unwrap()
.vertex_index();
selection.contains(&from_vertex.into()) && selection.contains(&to_vertex.into())
})
.collect::<Vec<_>>(),
self,
)
} }
pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> { pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> {

View File

@ -33,6 +33,15 @@ pub enum RatsnestVertexIndex {
Zone(GenericIndex<ZoneWeight>), Zone(GenericIndex<ZoneWeight>),
} }
impl From<RatsnestVertexIndex> for crate::layout::NodeIndex {
fn from(vertex: RatsnestVertexIndex) -> crate::layout::NodeIndex {
match vertex {
RatsnestVertexIndex::FixedDot(dot) => crate::layout::NodeIndex::Primitive(dot.into()),
RatsnestVertexIndex::Zone(zone) => crate::layout::NodeIndex::Compound(zone.into()),
}
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct VertexWeight { pub struct VertexWeight {
vertex: RatsnestVertexIndex, vertex: RatsnestVertexIndex,

View File

@ -196,13 +196,15 @@ impl eframe::App for App {
ui.separator(); ui.separator();
if ui.button("Autoroute").clicked() { if ui.button("Autoroute").clicked() {
if let Some(layout_arc_mutex) = &self.layout { if let (Some(layout_arc_mutex), Some(overlay)) = (&self.layout, &self.overlay) {
let layout = layout_arc_mutex.clone(); let layout = layout_arc_mutex.clone();
let shared_data_arc_mutex = self.shared_data.clone(); let shared_data_arc_mutex = self.shared_data.clone();
let selection = overlay.selection().clone();
execute(async move { execute(async move {
let mut autorouter = Autorouter::new(layout).unwrap(); let mut autorouter = Autorouter::new(layout).unwrap();
if let Some(mut autoroute) = autorouter.autoroute_walk() {
if let Some(mut autoroute) = autorouter.autoroute_walk(&selection) {
let from = autoroute.navmesh().as_ref().unwrap().from(); let from = autoroute.navmesh().as_ref().unwrap().from();
let to = autoroute.navmesh().as_ref().unwrap().to(); let to = autoroute.navmesh().as_ref().unwrap().to();