diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index f9c1583..92debc6 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -22,7 +22,7 @@ use crate::{ rules::RulesTrait, }, layout::{Layout, NodeIndex}, - router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError}, + router::{navmesh::Navmesh, Router, RouterError, RouterObserverTrait}, triangulation::GetVertexIndex, }; @@ -73,12 +73,12 @@ impl Autoroute { (None, None) }; - let router = Router::new_from_navmesh( + let mut router = Router::new_from_navmesh( &mut autorouter.layout, std::mem::replace(&mut self.navmesh, new_navmesh).unwrap(), ); - let Ok(band) = router.unwrap().route_band(100.0, observer) else { + let Ok(band) = router.route_band(100.0, observer) else { return false; }; diff --git a/src/router/astar.rs b/src/router/astar.rs index 8e5f62f..56a6c8f 100644 --- a/src/router/astar.rs +++ b/src/router/astar.rs @@ -11,6 +11,7 @@ use std::hash::Hash; use petgraph::algo::Measure; use petgraph::visit::{EdgeRef, GraphBase, IntoEdges}; +use thiserror::Error; use std::cmp::Ordering; @@ -105,7 +106,7 @@ where fn estimate_cost(&mut self, node: G::NodeId) -> K; } -struct Astar +pub struct Astar where G: IntoEdges, G::NodeId: Eq + Hash, @@ -118,15 +119,21 @@ where pub path_tracker: PathTracker, } -enum AstarStatus +#[derive(Error, Debug, Clone)] +pub enum AstarError { + #[error("A* search found no path")] + NotFound, +} + +pub enum AstarStatus where G: IntoEdges, G::NodeId: Eq + Hash, K: Measure + Copy, { Running, - Success(K, Vec, R), - Failure, + Finished(K, Vec, R), + Error(AstarError), } impl Astar @@ -153,13 +160,13 @@ where pub fn step(&mut self, strategy: &mut impl AstarStrategy) -> AstarStatus { let Some(MinScored(estimate_score, node)) = self.visit_next.pop() else { - return AstarStatus::Failure; + return AstarStatus::Error(AstarError::NotFound); }; if let Some(result) = strategy.is_goal(node, &self.path_tracker) { let path = self.path_tracker.reconstruct_path_to(node); let cost = self.scores[&node]; - return AstarStatus::Success(cost, path, result); + return AstarStatus::Finished(cost, path, result); } // This lookup can be unwrapped without fear of panic since the node was @@ -213,7 +220,7 @@ pub fn astar( graph: G, start: G::NodeId, strategy: &mut impl AstarStrategy, -) -> Option<(K, Vec, R)> +) -> Result<(K, Vec, R), AstarError> where G: IntoEdges, G::NodeId: Eq + Hash, @@ -221,9 +228,17 @@ where { let mut astar = Astar::new(graph, start, strategy); - while let AstarStatus::Running = astar.step(strategy) { - // - } + loop { + let status = astar.step(strategy); - None + /*if !matches!(status, AstarStatus::Running) { + return status; + }*/ + + match status { + AstarStatus::Running => (), + AstarStatus::Finished(cost, path, band) => return Ok((cost, path, band)), + AstarStatus::Error(err) => return Err(err), + } + } } diff --git a/src/router/navmesh.rs b/src/router/navmesh.rs index 4e89d0a..e2dbf54 100644 --- a/src/router/navmesh.rs +++ b/src/router/navmesh.rs @@ -6,6 +6,7 @@ use itertools::Itertools; use petgraph::visit::{self, NodeIndexable}; use petgraph::{stable_graph::NodeIndex, visit::EdgeRef}; use spade::{HasPosition, InsertionError, Point2}; +use thiserror::Error; use crate::drawing::graph::{GetLayer, GetMaybeNet}; use crate::geometry::shape::ShapeTrait; @@ -85,12 +86,18 @@ pub struct Navmesh { to: FixedDotIndex, } +#[derive(Error, Debug, Clone)] +pub enum NavmeshError { + #[error("failed to insert vertex in navmesh")] + Insertion(#[from] InsertionError), +} + impl Navmesh { pub fn new( layout: &Layout, from: FixedDotIndex, to: FixedDotIndex, - ) -> Result { + ) -> Result { let mut this = Self { triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()), vertex_to_triangulation_vertex: Vec::new(), diff --git a/src/router/router.rs b/src/router/router.rs index e7cf3c3..21afa18 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -6,31 +6,28 @@ use petgraph::visit::EdgeRef; use spade::InsertionError; use thiserror::Error; -use crate::drawing::band::BandIndex; -use crate::drawing::graph::{GetLayer, GetMaybeNet}; -use crate::drawing::guide::HeadTrait; -use crate::geometry::primitive::PrimitiveShapeTrait; -use crate::layout::Layout; use crate::{ drawing::{ + band::BandIndex, dot::FixedDotIndex, graph::{MakePrimitive, PrimitiveIndex}, + guide::HeadTrait, primitive::MakePrimitiveShape, rules::RulesTrait, }, geometry::shape::ShapeTrait, + layout::Layout, + router::{ + astar::{astar, AstarError, AstarStrategy, PathTracker}, + draw::DrawException, + navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, VertexIndex}, + tracer::{Trace, Tracer}, + }, }; -use crate::router::{ - astar::{astar, AstarStrategy, PathTracker}, - draw::DrawException, - navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex}, - tracer::{Trace, Tracer}, -}; - -#[derive(Error, Debug, Clone, Copy)] +/*#[derive(Error, Debug, Clone, Copy)] #[error("failed to route from {from:?} to {to:?}")] // this should eventually use Display -pub struct RoutingError { +pub struct RouterError { from: FixedDotIndex, to: FixedDotIndex, source: RoutingErrorKind, @@ -44,6 +41,13 @@ pub enum RoutingErrorKind { // TODO more descriptive message #[error("A* found no path")] AStar, +}*/ + +#[derive(Error, Debug, Clone)] +#[error("routing failed")] +pub enum RouterError { + Navmesh(#[from] NavmeshError), + Astar(#[from] AstarError), } pub trait RouterObserverTrait { @@ -169,26 +173,23 @@ impl<'a, R: RulesTrait> Router<'a, R> { layout: &'a mut Arc>>, from: FixedDotIndex, to: FixedDotIndex, - ) -> Result { + ) -> Result { let navmesh = { let layout = layout.lock().unwrap(); Navmesh::new(&layout, from, to)? }; - Self::new_from_navmesh(layout, navmesh) + Ok(Self::new_from_navmesh(layout, navmesh)) } - pub fn new_from_navmesh( - layout: &'a mut Arc>>, - navmesh: Navmesh, - ) -> Result { - Ok(Self { layout, navmesh }) + pub fn new_from_navmesh(layout: &'a mut Arc>>, navmesh: Navmesh) -> Self { + Self { layout, navmesh } } pub fn route_band( &mut self, width: f64, observer: &mut impl RouterObserverTrait, - ) -> Result { + ) -> Result { let mut tracer = self.tracer(); let trace = tracer.start(self.navmesh.from(), width); @@ -196,12 +197,7 @@ impl<'a, R: RulesTrait> Router<'a, R> { &self.navmesh, self.navmesh.from().into(), &mut RouterAstarStrategy::new(tracer, trace, self.navmesh.to(), observer), - ) - .ok_or(RoutingError { - from: self.navmesh.from(), - to: self.navmesh.to(), - source: RoutingErrorKind::AStar, - })?; + )?; Ok(band) }