mirror of https://codeberg.org/topola/topola.git
router: use `Step` and new `StepBack` traits in `Route` and `Trace`
This commit is contained in:
parent
1305487c7f
commit
7830806834
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
tracer::Tracer,
|
tracer::Tracer,
|
||||||
Router, RouterAstarStrategy, RouterError, RouterStatus,
|
Router, RouterAstarStrategy, RouterError, RouterStatus,
|
||||||
},
|
},
|
||||||
|
step::Step,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Route {
|
pub struct Route {
|
||||||
|
|
@ -53,26 +54,6 @@ impl Route {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(
|
|
||||||
&mut self,
|
|
||||||
router: &mut Router<impl AccessRules>,
|
|
||||||
) -> Result<RouterStatus, RouterError> {
|
|
||||||
let tracer = Tracer::new(router.layout_mut());
|
|
||||||
let target = self.astar.graph.destination();
|
|
||||||
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
|
|
||||||
|
|
||||||
let result = match self.astar.step(&mut strategy)? {
|
|
||||||
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {
|
|
||||||
Ok(RouterStatus::Running)
|
|
||||||
}
|
|
||||||
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.ghosts = strategy.probe_ghosts;
|
|
||||||
self.obstacles = strategy.probe_obstacles;
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn navmesh(&self) -> &Navmesh {
|
pub fn navmesh(&self) -> &Navmesh {
|
||||||
&self.astar.graph
|
&self.astar.graph
|
||||||
}
|
}
|
||||||
|
|
@ -89,3 +70,22 @@ impl Route {
|
||||||
&self.obstacles
|
&self.obstacles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, RouterError> 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();
|
||||||
|
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
|
||||||
|
|
||||||
|
let result = match self.astar.step(&mut strategy)? {
|
||||||
|
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {
|
||||||
|
Ok(RouterStatus::Running)
|
||||||
|
}
|
||||||
|
AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.ghosts = strategy.probe_ghosts;
|
||||||
|
self.obstacles = strategy.probe_obstacles;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
graph::{GetPetgraphIndex, MakeRef},
|
graph::{GetPetgraphIndex, MakeRef},
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
|
step::{IsFinished, Step, StepBack},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -25,7 +26,7 @@ use super::{
|
||||||
draw::DrawException,
|
draw::DrawException,
|
||||||
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
|
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
|
||||||
route::Route,
|
route::Route,
|
||||||
trace::Trace,
|
trace::{Trace, TraceStepInput},
|
||||||
tracer::{Tracer, TracerException},
|
tracer::{Tracer, TracerException},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -42,6 +43,12 @@ pub enum RouterStatus {
|
||||||
Finished(BandTermsegIndex),
|
Finished(BandTermsegIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IsFinished for RouterStatus {
|
||||||
|
fn finished(&self) -> bool {
|
||||||
|
matches!(self, RouterStatus::Finished(..))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
pub struct RouterAstarStrategy<'a, R: AccessRules> {
|
||||||
pub tracer: Tracer<'a, R>,
|
pub tracer: Tracer<'a, R>,
|
||||||
|
|
@ -107,9 +114,12 @@ 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
|
let result = self.trace.step(&mut TraceStepInput {
|
||||||
.trace
|
tracer: &mut self.tracer,
|
||||||
.step(&mut self.tracer, navmesh, edge.target(), width);
|
navmesh,
|
||||||
|
to: edge.target(),
|
||||||
|
width,
|
||||||
|
});
|
||||||
|
|
||||||
let probe_length = self.bihead_length() - prev_bihead_length;
|
let probe_length = self.bihead_length() - prev_bihead_length;
|
||||||
|
|
||||||
|
|
@ -141,7 +151,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_probe(&mut self, _navmesh: &Navmesh) {
|
fn remove_probe(&mut self, _navmesh: &Navmesh) {
|
||||||
self.trace.undo_step(&mut self.tracer);
|
self.trace.step_back(&mut self.tracer);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {
|
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,14 @@ use crate::{
|
||||||
head::{BareHead, CaneHead, Head},
|
head::{BareHead, CaneHead, Head},
|
||||||
rules::AccessRules,
|
rules::AccessRules,
|
||||||
},
|
},
|
||||||
router::{
|
step::{Step, StepBack},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
|
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
|
||||||
|
tracer::TracerStatus,
|
||||||
tracer::{Tracer, TracerException},
|
tracer::{Tracer, TracerException},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -32,33 +35,6 @@ impl Trace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.path.len() == old(self.path.len() + 1))]
|
|
||||||
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
|
|
||||||
pub fn step(
|
|
||||||
&mut self,
|
|
||||||
tracer: &mut Tracer<impl AccessRules>,
|
|
||||||
navmesh: &Navmesh,
|
|
||||||
to: NavvertexIndex,
|
|
||||||
width: f64,
|
|
||||||
) -> Result<(), TracerException> {
|
|
||||||
self.head = self.wrap(tracer, navmesh, self.head, to, width)?.into();
|
|
||||||
self.path.push(to);
|
|
||||||
|
|
||||||
Ok::<(), TracerException>(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
|
|
||||||
pub fn undo_step(&mut self, tracer: &mut Tracer<impl AccessRules>) {
|
|
||||||
if let Head::Cane(head) = self.head {
|
|
||||||
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap();
|
|
||||||
} else {
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.path.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wrap(
|
fn wrap(
|
||||||
&mut self,
|
&mut self,
|
||||||
tracer: &mut Tracer<impl AccessRules>,
|
tracer: &mut Tracer<impl AccessRules>,
|
||||||
|
|
@ -116,3 +92,49 @@ impl Trace {
|
||||||
navmesh.node_weight(navvertex).unwrap().maybe_cw
|
navmesh.node_weight(navvertex).unwrap().maybe_cw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TraceStepInput<'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>
|
||||||
|
for Trace
|
||||||
|
{
|
||||||
|
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
|
||||||
|
#[debug_ensures(ret.is_ok() -> self.path.len() == old(self.path.len() + 1))]
|
||||||
|
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
|
||||||
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
input: &mut TraceStepInput<'a, 'b, R>,
|
||||||
|
) -> Result<TracerStatus, TracerException> {
|
||||||
|
self.head = self
|
||||||
|
.wrap(
|
||||||
|
input.tracer,
|
||||||
|
input.navmesh,
|
||||||
|
self.head,
|
||||||
|
input.to,
|
||||||
|
input.width,
|
||||||
|
)?
|
||||||
|
.into();
|
||||||
|
self.path.push(input.to);
|
||||||
|
|
||||||
|
Ok(TracerStatus::Running)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R: AccessRules> StepBack<Tracer<'a, R>, TracerStatus, TracerException> for Trace {
|
||||||
|
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
|
||||||
|
fn step_back(&mut self, tracer: &mut Tracer<'a, R>) -> Result<TracerStatus, TracerException> {
|
||||||
|
if let Head::Cane(head) = self.head {
|
||||||
|
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap();
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.path.pop();
|
||||||
|
Ok(TracerStatus::Running)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +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,
|
||||||
router::{
|
step::{IsFinished, Step, StepBack},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
draw::{Draw, DrawException},
|
draw::{Draw, DrawException},
|
||||||
navmesh::{Navmesh, NavvertexIndex},
|
navmesh::{Navmesh, NavvertexIndex},
|
||||||
trace::Trace,
|
trace::{Trace, TraceStepInput},
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone, Copy)]
|
#[derive(Error, Debug, Clone, Copy)]
|
||||||
|
|
@ -19,6 +21,17 @@ pub enum TracerException {
|
||||||
CannotWrap,
|
CannotWrap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum TracerStatus {
|
||||||
|
Running,
|
||||||
|
Finished,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsFinished for TracerStatus {
|
||||||
|
fn finished(&self) -> bool {
|
||||||
|
matches!(self, TracerStatus::Finished)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Tracer<'a, R: AccessRules> {
|
pub struct Tracer<'a, R: AccessRules> {
|
||||||
pub layout: &'a mut Layout<R>,
|
pub layout: &'a mut Layout<R>,
|
||||||
|
|
@ -78,7 +91,12 @@ 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(self, navmesh, *vertex, width) {
|
if let Err(err) = trace.step(&mut TraceStepInput {
|
||||||
|
tracer: self,
|
||||||
|
navmesh,
|
||||||
|
to: *vertex,
|
||||||
|
width,
|
||||||
|
}) {
|
||||||
self.undo_path(trace, i);
|
self.undo_path(trace, i);
|
||||||
return Err(err.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +108,7 @@ impl<'a, R: AccessRules> Tracer<'a, R> {
|
||||||
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
|
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
|
||||||
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
|
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
|
||||||
for _ in 0..step_count {
|
for _ in 0..step_count {
|
||||||
trace.undo_step(self);
|
let _ = trace.step_back(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@ pub trait IsFinished {
|
||||||
fn finished(&self) -> bool;
|
fn finished(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Step<C, S: IsFinished, E> {
|
pub trait Step<I, S: IsFinished, E> {
|
||||||
fn step(&mut self, context: &mut C) -> Result<S, E>;
|
fn step(&mut self, input: &mut I) -> Result<S, E>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait StepBack<I, S: IsFinished, E> {
|
||||||
|
fn step_back(&mut self, input: &mut I) -> Result<S, E>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue