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},
layout::via::ViaWeight,
router::{navmesh::NavmeshError, RouterError},
step::{GetMaybeOutcome, Step},
triangulation::GetTrianvertexNodeIndex,
};
@ -37,9 +36,14 @@ pub enum AutorouterStatus {
Finished,
}
impl GetMaybeOutcome<()> for AutorouterStatus {
fn maybe_outcome(&self) -> Option<()> {
matches!(self, AutorouterStatus::Finished).then(|| ())
impl TryInto<()> for AutorouterStatus {
type Error = ();
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,
layout::via::ViaWeight,
router::{navmesh::Navmesh, trace::Trace},
step::{GetMaybeOutcome, Step},
step::Step,
};
use super::{
@ -55,9 +55,13 @@ pub enum InvokerStatus {
Finished,
}
impl GetMaybeOutcome<()> for InvokerStatus {
fn maybe_outcome(&self) -> Option<()> {
matches!(self, InvokerStatus::Finished).then(|| ())
impl TryInto<()> for InvokerStatus {
type Error = ();
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 crate::step::Step;
#[derive(Copy, Clone, Debug)]
pub struct MinScored<K, T>(pub K, pub T);
@ -156,6 +158,24 @@ where
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>
where
G: GraphBase,
@ -183,11 +203,17 @@ where
));
this
}
}
pub fn step<R>(
&mut self,
strategy: &mut impl AstarStrategy<G, K, R>,
) -> Result<AstarStatus<G, K, R>, AstarError> {
impl<G, K, R, S: AstarStrategy<G, K, R>>
Step<S, AstarStatus<G, K, R>, AstarError, (K, Vec<G::NodeId>, R)> for Astar<G, K>
where
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 self.is_probing {
strategy.remove_probe(&self.graph);
@ -263,28 +289,3 @@ where
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::{
drawing::{dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules},
drawing::{
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
},
geometry::primitive::PrimitiveShape,
router::{
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> {
let tracer = Tracer::new(router.layout_mut());
let target = self.astar.graph.destination();

View File

@ -1,3 +1,5 @@
use std::convert::Infallible;
use geo::EuclideanDistance;
use petgraph::{data::DataMap, visit::EdgeRef};
use thiserror::Error;
@ -18,7 +20,7 @@ use crate::{
},
graph::{GetPetgraphIndex, MakeRef},
layout::Layout,
step::{GetMaybeOutcome, Step, StepBack},
step::{Step, StepBack},
};
use super::{
@ -26,7 +28,7 @@ use super::{
draw::DrawException,
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
route::Route,
trace::{Trace, TraceStepInput},
trace::{Trace, TraceStepContext},
tracer::{Tracer, TracerException},
};
@ -43,9 +45,13 @@ pub enum RouterStatus {
Finished(BandTermsegIndex),
}
impl GetMaybeOutcome<()> for RouterStatus {
fn maybe_outcome(&self) -> Option<()> {
matches!(self, RouterStatus::Finished(..)).then(|| ())
impl TryInto<BandTermsegIndex> for RouterStatus {
type Error = ();
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 width = self.trace.width;
let result = self.trace.step(&mut TraceStepInput {
let result = self.trace.step(&mut TraceStepContext {
tracer: &mut self.tracer,
navmesh,
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 navmesh: &'b Navmesh,
pub to: NavvertexIndex,
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
{
#[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()))]
fn step(
&mut self,
input: &mut TraceStepInput<'a, 'b, R>,
input: &mut TraceStepContext<'a, 'b, R>,
) -> Result<TracerStatus, TracerException> {
self.head = self
.wrap(

View File

@ -4,13 +4,13 @@ use thiserror::Error;
use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout,
step::{GetMaybeOutcome, Step, StepBack},
step::{Step, StepBack},
};
use super::{
draw::{Draw, DrawException},
navmesh::{Navmesh, NavvertexIndex},
trace::{Trace, TraceStepInput},
trace::{Trace, TraceStepContext},
};
#[derive(Error, Debug, Clone, Copy)]
@ -26,9 +26,13 @@ pub enum TracerStatus {
Finished,
}
impl GetMaybeOutcome<()> for TracerStatus {
fn maybe_outcome(&self) -> Option<()> {
matches!(self, TracerStatus::Finished).then(|| ())
impl TryInto<()> for TracerStatus {
type Error = ();
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,
) -> Result<(), TracerException> {
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,
navmesh,
to: *vertex,

View File

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