mirror of https://codeberg.org/topola/topola.git
router: use `Step` trait for `Astar` too
This commit is contained in:
parent
ece9c4aa5a
commit
43b48e78e3
|
|
@ -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(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
10
src/step.rs
10
src/step.rs
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue