diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index d0a49ae..7a447ad 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -1,11 +1,12 @@ use std::{ + collections::HashSet, iter::Peekable, sync::{Arc, Mutex}, }; use geo::Point; use petgraph::{ - graph::{EdgeIndex, EdgeIndices, NodeIndex}, + graph::{EdgeIndex, EdgeIndices}, visit::{EdgeRef, IntoEdgeReferences}, }; use spade::InsertionError; @@ -17,22 +18,24 @@ use crate::{ graph::{GetLayer, GetMaybeNet}, rules::RulesTrait, }, - layout::{connectivity::BandIndex, Layout}, + layout::{connectivity::BandIndex, Layout, NodeIndex}, router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError}, triangulation::GetVertexIndex, }; pub struct Autoroute { - edge_indices: EdgeIndices, + ratlines_iter: Box>>, navmesh: Option, // Useful for debugging. } impl Autoroute { pub fn new( - mut edge_indices: EdgeIndices, + ratlines: impl IntoIterator> + 'static, autorouter: &mut Autorouter, ) -> Option { - 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; }; @@ -41,7 +44,7 @@ impl Autoroute { let navmesh = Some(Navmesh::new(&layout, from, to).ok()?); let this = Self { - edge_indices, + ratlines_iter, navmesh, }; @@ -53,7 +56,7 @@ impl Autoroute { autorouter: &mut Autorouter, observer: &mut impl RouterObserverTrait, ) -> 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 layout = autorouter.layout.lock().unwrap(); @@ -119,16 +122,44 @@ impl Autorouter { Ok(Self { layout, ratsnest }) } - pub fn autoroute(&mut self, layer: u64, observer: &mut impl RouterObserverTrait) { - if let Some(mut autoroute) = self.autoroute_walk() { + pub fn autoroute( + &mut self, + selection: &HashSet, + observer: &mut impl RouterObserverTrait, + ) { + if let Some(mut autoroute) = self.autoroute_walk(selection) { while autoroute.next(self, observer) { // } } } - pub fn autoroute_walk(&mut self) -> Option { - Autoroute::new(self.ratsnest.graph().edge_indices(), self) + pub fn autoroute_walk(&mut self, selection: &HashSet) -> Option { + 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::>(), + self, + ) } pub fn layout(&self) -> &Arc>> { diff --git a/src/autorouter/ratsnest.rs b/src/autorouter/ratsnest.rs index fceb64f..8d2b8c2 100644 --- a/src/autorouter/ratsnest.rs +++ b/src/autorouter/ratsnest.rs @@ -33,6 +33,15 @@ pub enum RatsnestVertexIndex { Zone(GenericIndex), } +impl From 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)] pub struct VertexWeight { vertex: RatsnestVertexIndex, diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index ea480c7..dda88cc 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -196,13 +196,15 @@ impl eframe::App for App { ui.separator(); 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 shared_data_arc_mutex = self.shared_data.clone(); + let selection = overlay.selection().clone(); execute(async move { 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 to = autoroute.navmesh().as_ref().unwrap().to();