router: use `Step` trait for `Astar` too

This commit is contained in:
Mikolaj Wielgus 2024-08-04 18:50:58 +02:00
parent ece9c4aa5a
commit 43b48e78e3
8 changed files with 80 additions and 61 deletions

View File

@ -7,7 +7,6 @@ use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement},
layout::via::ViaWeight, layout::via::ViaWeight,
router::{navmesh::NavmeshError, RouterError}, router::{navmesh::NavmeshError, RouterError},
step::{GetMaybeOutcome, Step},
triangulation::GetTrianvertexNodeIndex, triangulation::GetTrianvertexNodeIndex,
}; };
@ -37,9 +36,14 @@ pub enum AutorouterStatus {
Finished, Finished,
} }
impl GetMaybeOutcome<()> for AutorouterStatus { impl TryInto<()> for AutorouterStatus {
fn maybe_outcome(&self) -> Option<()> { type Error = ();
matches!(self, AutorouterStatus::Finished).then(|| ()) fn try_into(self) -> Result<(), ()> {
match self {
AutorouterStatus::Running => Err(()),
AutorouterStatus::Routed(..) => Err(()),
AutorouterStatus::Finished => Ok(()),
}
} }
} }

View File

@ -9,7 +9,7 @@ use crate::{
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
layout::via::ViaWeight, layout::via::ViaWeight,
router::{navmesh::Navmesh, trace::Trace}, router::{navmesh::Navmesh, trace::Trace},
step::{GetMaybeOutcome, Step}, step::Step,
}; };
use super::{ use super::{
@ -55,9 +55,13 @@ pub enum InvokerStatus {
Finished, Finished,
} }
impl GetMaybeOutcome<()> for InvokerStatus { impl TryInto<()> for InvokerStatus {
fn maybe_outcome(&self) -> Option<()> { type Error = ();
matches!(self, InvokerStatus::Finished).then(|| ()) fn try_into(self) -> Result<(), ()> {
match self {
InvokerStatus::Running => Err(()),
InvokerStatus::Finished => Ok(()),
}
} }
} }

View File

@ -15,6 +15,8 @@ use thiserror::Error;
use std::cmp::Ordering; use std::cmp::Ordering;
use crate::step::Step;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct MinScored<K, T>(pub K, pub T); pub struct MinScored<K, T>(pub K, pub T);
@ -156,6 +158,24 @@ where
Finished(K, Vec<G::NodeId>, R), Finished(K, Vec<G::NodeId>, R),
} }
impl<G, K, R> TryInto<(K, Vec<G::NodeId>, R)> for AstarStatus<G, K, R>
where
G: GraphBase,
G::NodeId: Eq + Hash,
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
K: Measure + Copy,
{
type Error = ();
fn try_into(self) -> Result<(K, Vec<G::NodeId>, R), ()> {
match self {
AstarStatus::Probing => Err(()),
AstarStatus::Probed => Err(()),
AstarStatus::Visited => Err(()),
AstarStatus::Finished(cost, path, result) => Ok((cost, path, result)),
}
}
}
impl<G, K> Astar<G, K> impl<G, K> Astar<G, K>
where where
G: GraphBase, G: GraphBase,
@ -183,11 +203,17 @@ where
)); ));
this this
} }
}
pub fn step<R>( impl<G, K, R, S: AstarStrategy<G, K, R>>
&mut self, Step<S, AstarStatus<G, K, R>, AstarError, (K, Vec<G::NodeId>, R)> for Astar<G, K>
strategy: &mut impl AstarStrategy<G, K, R>, where
) -> Result<AstarStatus<G, K, R>, AstarError> { G: GraphBase,
G::NodeId: Eq + Hash,
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
K: Measure + Copy,
{
fn step(&mut self, strategy: &mut S) -> Result<AstarStatus<G, K, R>, AstarError> {
if let Some(curr_node) = self.maybe_curr_node { if let Some(curr_node) = self.maybe_curr_node {
if self.is_probing { if self.is_probing {
strategy.remove_probe(&self.graph); strategy.remove_probe(&self.graph);
@ -263,28 +289,3 @@ where
Ok(AstarStatus::Visited) Ok(AstarStatus::Visited)
} }
} }
pub fn astar<G, K, R>(
graph: G,
start: G::NodeId,
strategy: &mut impl AstarStrategy<G, K, R>,
) -> Result<(K, Vec<G::NodeId>, R), AstarError>
where
G: GraphBase,
G::NodeId: Eq + Hash,
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
K: Measure + Copy,
{
let mut astar = Astar::new(graph, start, strategy);
loop {
let status = match astar.step(strategy) {
Ok(status) => status,
Err(err) => return Err(err),
};
if let AstarStatus::Finished(cost, path, band) = status {
return Ok((cost, path, band));
}
}
}

View File

@ -1,5 +1,7 @@
use crate::{ use crate::{
drawing::{dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules}, drawing::{
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
},
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{ router::{
astar::{Astar, AstarStatus}, astar::{Astar, AstarStatus},
@ -71,7 +73,9 @@ impl Route {
} }
} }
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, RouterError, ()> for Route { impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, RouterError, BandTermsegIndex>
for Route
{
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, RouterError> { fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, RouterError> {
let tracer = Tracer::new(router.layout_mut()); let tracer = Tracer::new(router.layout_mut());
let target = self.astar.graph.destination(); let target = self.astar.graph.destination();

View File

@ -1,3 +1,5 @@
use std::convert::Infallible;
use geo::EuclideanDistance; use geo::EuclideanDistance;
use petgraph::{data::DataMap, visit::EdgeRef}; use petgraph::{data::DataMap, visit::EdgeRef};
use thiserror::Error; use thiserror::Error;
@ -18,7 +20,7 @@ use crate::{
}, },
graph::{GetPetgraphIndex, MakeRef}, graph::{GetPetgraphIndex, MakeRef},
layout::Layout, layout::Layout,
step::{GetMaybeOutcome, Step, StepBack}, step::{Step, StepBack},
}; };
use super::{ use super::{
@ -26,7 +28,7 @@ use super::{
draw::DrawException, draw::DrawException,
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex}, navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
route::Route, route::Route,
trace::{Trace, TraceStepInput}, trace::{Trace, TraceStepContext},
tracer::{Tracer, TracerException}, tracer::{Tracer, TracerException},
}; };
@ -43,9 +45,13 @@ pub enum RouterStatus {
Finished(BandTermsegIndex), Finished(BandTermsegIndex),
} }
impl GetMaybeOutcome<()> for RouterStatus { impl TryInto<BandTermsegIndex> for RouterStatus {
fn maybe_outcome(&self) -> Option<()> { type Error = ();
matches!(self, RouterStatus::Finished(..)).then(|| ()) fn try_into(self) -> Result<BandTermsegIndex, ()> {
match self {
RouterStatus::Running => Err(()),
RouterStatus::Finished(band_termseg) => Ok(band_termseg),
}
} }
} }
@ -114,7 +120,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
let prev_bihead_length = self.bihead_length(); let prev_bihead_length = self.bihead_length();
let width = self.trace.width; let width = self.trace.width;
let result = self.trace.step(&mut TraceStepInput { let result = self.trace.step(&mut TraceStepContext {
tracer: &mut self.tracer, tracer: &mut self.tracer,
navmesh, navmesh,
to: edge.target(), to: edge.target(),

View File

@ -93,14 +93,14 @@ impl Trace {
} }
} }
pub struct TraceStepInput<'a: 'b, 'b, R: AccessRules> { pub struct TraceStepContext<'a: 'b, 'b, R: AccessRules> {
pub tracer: &'b mut Tracer<'a, R>, pub tracer: &'b mut Tracer<'a, R>,
pub navmesh: &'b Navmesh, pub navmesh: &'b Navmesh,
pub to: NavvertexIndex, pub to: NavvertexIndex,
pub width: f64, pub width: f64,
} }
impl<'a, 'b, R: AccessRules> Step<TraceStepInput<'a, 'b, R>, TracerStatus, TracerException, ()> impl<'a, 'b, R: AccessRules> Step<TraceStepContext<'a, 'b, R>, TracerStatus, TracerException, ()>
for Trace for Trace
{ {
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))] #[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
@ -108,7 +108,7 @@ impl<'a, 'b, R: AccessRules> Step<TraceStepInput<'a, 'b, R>, TracerStatus, Trace
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))] #[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
fn step( fn step(
&mut self, &mut self,
input: &mut TraceStepInput<'a, 'b, R>, input: &mut TraceStepContext<'a, 'b, R>,
) -> Result<TracerStatus, TracerException> { ) -> Result<TracerStatus, TracerException> {
self.head = self self.head = self
.wrap( .wrap(

View File

@ -4,13 +4,13 @@ use thiserror::Error;
use crate::{ use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout, layout::Layout,
step::{GetMaybeOutcome, Step, StepBack}, step::{Step, StepBack},
}; };
use super::{ use super::{
draw::{Draw, DrawException}, draw::{Draw, DrawException},
navmesh::{Navmesh, NavvertexIndex}, navmesh::{Navmesh, NavvertexIndex},
trace::{Trace, TraceStepInput}, trace::{Trace, TraceStepContext},
}; };
#[derive(Error, Debug, Clone, Copy)] #[derive(Error, Debug, Clone, Copy)]
@ -26,9 +26,13 @@ pub enum TracerStatus {
Finished, Finished,
} }
impl GetMaybeOutcome<()> for TracerStatus { impl TryInto<()> for TracerStatus {
fn maybe_outcome(&self) -> Option<()> { type Error = ();
matches!(self, TracerStatus::Finished).then(|| ()) fn try_into(self) -> Result<(), ()> {
match self {
TracerStatus::Running => Err(()),
TracerStatus::Finished => Ok(()),
}
} }
} }
@ -91,7 +95,7 @@ impl<'a, R: AccessRules> Tracer<'a, R> {
width: f64, width: f64,
) -> Result<(), TracerException> { ) -> Result<(), TracerException> {
for (i, vertex) in path.iter().enumerate() { for (i, vertex) in path.iter().enumerate() {
if let Err(err) = trace.step(&mut TraceStepInput { if let Err(err) = trace.step(&mut TraceStepContext {
tracer: self, tracer: self,
navmesh, navmesh,
to: *vertex, to: *vertex,

View File

@ -1,19 +1,15 @@
pub trait GetMaybeOutcome<O> { pub trait Step<C, S: TryInto<O>, E, O> {
fn maybe_outcome(&self) -> Option<O>;
}
pub trait Step<C, S: GetMaybeOutcome<O>, E, O> {
fn step(&mut self, context: &mut C) -> Result<S, E>; fn step(&mut self, context: &mut C) -> Result<S, E>;
fn finish(&mut self, context: &mut C) -> Result<O, E> { fn finish(&mut self, context: &mut C) -> Result<O, E> {
loop { loop {
if let Some(outcome) = self.step(context)?.maybe_outcome() { if let Ok(outcome) = self.step(context)?.try_into() {
return Ok(outcome); return Ok(outcome);
} }
} }
} }
} }
pub trait StepBack<C, S: GetMaybeOutcome<O>, E, O> { pub trait StepBack<C, S: TryInto<O>, E, O> {
fn step_back(&mut self, context: &mut C) -> Result<S, E>; fn step_back(&mut self, context: &mut C) -> Result<S, E>;
} }