mirror of https://codeberg.org/topola/topola.git
router: improve error handling -- more error types, remove some unwraps
This commit is contained in:
parent
af9cbeba61
commit
a4503a42c6
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<G, K>
|
||||
pub struct Astar<G, K>
|
||||
where
|
||||
G: IntoEdges,
|
||||
G::NodeId: Eq + Hash,
|
||||
|
|
@ -118,15 +119,21 @@ where
|
|||
pub path_tracker: PathTracker<G>,
|
||||
}
|
||||
|
||||
enum AstarStatus<G, K, R>
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum AstarError {
|
||||
#[error("A* search found no path")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
pub enum AstarStatus<G, K, R>
|
||||
where
|
||||
G: IntoEdges,
|
||||
G::NodeId: Eq + Hash,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
Running,
|
||||
Success(K, Vec<G::NodeId>, R),
|
||||
Failure,
|
||||
Finished(K, Vec<G::NodeId>, R),
|
||||
Error(AstarError),
|
||||
}
|
||||
|
||||
impl<G, K> Astar<G, K>
|
||||
|
|
@ -153,13 +160,13 @@ where
|
|||
|
||||
pub fn step<R>(&mut self, strategy: &mut impl AstarStrategy<G, K, R>) -> AstarStatus<G, K, R> {
|
||||
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<G, K, R>(
|
|||
graph: G,
|
||||
start: G::NodeId,
|
||||
strategy: &mut impl AstarStrategy<G, K, R>,
|
||||
) -> Option<(K, Vec<G::NodeId>, R)>
|
||||
) -> Result<(K, Vec<G::NodeId>, 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<impl RulesTrait>,
|
||||
from: FixedDotIndex,
|
||||
to: FixedDotIndex,
|
||||
) -> Result<Self, InsertionError> {
|
||||
) -> Result<Self, NavmeshError> {
|
||||
let mut this = Self {
|
||||
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
|
||||
vertex_to_triangulation_vertex: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -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<R: RulesTrait> {
|
||||
|
|
@ -169,26 +173,23 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
|||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
||||
from: FixedDotIndex,
|
||||
to: FixedDotIndex,
|
||||
) -> Result<Self, InsertionError> {
|
||||
) -> Result<Self, RouterError> {
|
||||
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<Mutex<Layout<R>>>,
|
||||
navmesh: Navmesh,
|
||||
) -> Result<Self, InsertionError> {
|
||||
Ok(Self { layout, navmesh })
|
||||
pub fn new_from_navmesh(layout: &'a mut Arc<Mutex<Layout<R>>>, navmesh: Navmesh) -> Self {
|
||||
Self { layout, navmesh }
|
||||
}
|
||||
|
||||
pub fn route_band(
|
||||
&mut self,
|
||||
width: f64,
|
||||
observer: &mut impl RouterObserverTrait<R>,
|
||||
) -> Result<BandIndex, RoutingError> {
|
||||
) -> Result<BandIndex, RouterError> {
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue