mirror of https://codeberg.org/topola/topola.git
refactor(router::navcorder): turn Navcorder into a trait
This commit is contained in:
parent
1d11011133
commit
90544c12ed
|
|
@ -13,12 +13,12 @@ use crate::{
|
||||||
head::{BareHead, CaneHead, Head},
|
head::{BareHead, CaneHead, Head},
|
||||||
rules::AccessRules,
|
rules::AccessRules,
|
||||||
},
|
},
|
||||||
layout::LayoutEdit,
|
layout::{Layout, LayoutEdit},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
navcorder::{Navcorder, NavcorderException},
|
navcorder::NavcorderException,
|
||||||
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
|
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ impl NavcordStepper {
|
||||||
|
|
||||||
fn wrap(
|
fn wrap(
|
||||||
&mut self,
|
&mut self,
|
||||||
navcorder: &mut Navcorder<impl AccessRules>,
|
layout: &mut Layout<impl AccessRules>,
|
||||||
navmesh: &Navmesh,
|
navmesh: &Navmesh,
|
||||||
head: Head,
|
head: Head,
|
||||||
around: NavvertexIndex,
|
around: NavvertexIndex,
|
||||||
|
|
@ -68,39 +68,35 @@ impl NavcordStepper {
|
||||||
|
|
||||||
match self.binavvertex(navmesh, around) {
|
match self.binavvertex(navmesh, around) {
|
||||||
BinavvertexNodeIndex::FixedDot(dot) => {
|
BinavvertexNodeIndex::FixedDot(dot) => {
|
||||||
self.wrap_around_fixed_dot(navcorder, head, dot, cw, width)
|
self.wrap_around_fixed_dot(layout, head, dot, cw, width)
|
||||||
}
|
}
|
||||||
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
|
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
|
||||||
BinavvertexNodeIndex::LooseBend(loose_bend) => {
|
BinavvertexNodeIndex::LooseBend(loose_bend) => {
|
||||||
self.wrap_around_loose_bend(navcorder, head, loose_bend, cw, width)
|
self.wrap_around_loose_bend(layout, head, loose_bend, cw, width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_around_fixed_dot(
|
fn wrap_around_fixed_dot(
|
||||||
&mut self,
|
&mut self,
|
||||||
navcorder: &mut Navcorder<impl AccessRules>,
|
layout: &mut Layout<impl AccessRules>,
|
||||||
head: Head,
|
head: Head,
|
||||||
around: FixedDotIndex,
|
around: FixedDotIndex,
|
||||||
cw: bool,
|
cw: bool,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<CaneHead, NavcorderException> {
|
) -> Result<CaneHead, NavcorderException> {
|
||||||
Ok(navcorder
|
Ok(layout.cane_around_dot(&mut self.recorder, head, around, cw, width)?)
|
||||||
.layout
|
|
||||||
.cane_around_dot(&mut self.recorder, head, around, cw, width)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_around_loose_bend(
|
fn wrap_around_loose_bend(
|
||||||
&mut self,
|
&mut self,
|
||||||
navcorder: &mut Navcorder<impl AccessRules>,
|
layout: &mut Layout<impl AccessRules>,
|
||||||
head: Head,
|
head: Head,
|
||||||
around: LooseBendIndex,
|
around: LooseBendIndex,
|
||||||
cw: bool,
|
cw: bool,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<CaneHead, NavcorderException> {
|
) -> Result<CaneHead, NavcorderException> {
|
||||||
Ok(navcorder
|
Ok(layout.cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?)
|
||||||
.layout
|
|
||||||
.cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
|
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
|
||||||
|
|
@ -116,9 +112,9 @@ impl NavcordStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NavcordStepContext<'a: 'b, 'b, R> {
|
pub struct NavcordStepContext<'a, R> {
|
||||||
pub navcorder: &'b mut Navcorder<'a, R>,
|
pub layout: &'a mut Layout<R>,
|
||||||
pub navmesh: &'b Navmesh,
|
pub navmesh: &'a Navmesh,
|
||||||
pub to: NavvertexIndex,
|
pub to: NavvertexIndex,
|
||||||
pub width: f64,
|
pub width: f64,
|
||||||
}
|
}
|
||||||
|
|
@ -127,13 +123,13 @@ impl NavcordStepper {
|
||||||
#[debug_ensures(ret.is_ok() -> matches!(self.head, Head::Cane(..)))]
|
#[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_ok() -> self.path.len() == old(self.path.len() + 1))]
|
||||||
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
|
#[debug_ensures(ret.is_err() -> self.path.len() == old(self.path.len()))]
|
||||||
pub fn step<'a, 'b, R: AccessRules>(
|
pub fn step<R: AccessRules>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &mut NavcordStepContext<'a, 'b, R>,
|
input: &mut NavcordStepContext<'_, R>,
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
self.head = self
|
self.head = self
|
||||||
.wrap(
|
.wrap(
|
||||||
input.navcorder,
|
input.layout,
|
||||||
input.navmesh,
|
input.navmesh,
|
||||||
self.head,
|
self.head,
|
||||||
input.to,
|
input.to,
|
||||||
|
|
@ -146,15 +142,12 @@ impl NavcordStepper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
|
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
|
||||||
pub fn step_back<'a, R: AccessRules>(
|
pub fn step_back<R: AccessRules>(
|
||||||
&mut self,
|
&mut self,
|
||||||
navcorder: &mut Navcorder<'a, R>,
|
layout: &mut Layout<R>,
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
if let Head::Cane(head) = self.head {
|
if let Head::Cane(head) = self.head {
|
||||||
self.head = navcorder
|
self.head = layout.undo_cane(&mut self.recorder, head).unwrap();
|
||||||
.layout
|
|
||||||
.undo_cane(&mut self.recorder, head)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,44 @@ pub enum NavcorderException {
|
||||||
CannotWrap,
|
CannotWrap,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub trait Navcorder {
|
||||||
pub struct Navcorder<'a, R> {
|
fn start(
|
||||||
pub layout: &'a mut Layout<R>,
|
&mut self,
|
||||||
|
recorder: LayoutEdit,
|
||||||
|
source: FixedDotIndex,
|
||||||
|
source_navvertex: NavvertexIndex,
|
||||||
|
width: f64,
|
||||||
|
) -> NavcordStepper;
|
||||||
|
|
||||||
|
fn finish(
|
||||||
|
&mut self,
|
||||||
|
_navmesh: &Navmesh,
|
||||||
|
navcord: &mut NavcordStepper,
|
||||||
|
target: FixedDotIndex,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<BandTermsegIndex, NavcorderException>;
|
||||||
|
|
||||||
|
fn rework_path(
|
||||||
|
&mut self,
|
||||||
|
navmesh: &Navmesh,
|
||||||
|
navcord: &mut NavcordStepper,
|
||||||
|
path: &[NavvertexIndex],
|
||||||
|
width: f64,
|
||||||
|
) -> Result<(), NavcorderException>;
|
||||||
|
|
||||||
|
fn path(
|
||||||
|
&mut self,
|
||||||
|
navmesh: &Navmesh,
|
||||||
|
navcord: &mut NavcordStepper,
|
||||||
|
path: &[NavvertexIndex],
|
||||||
|
width: f64,
|
||||||
|
) -> Result<(), NavcorderException>;
|
||||||
|
|
||||||
|
fn undo_path(&mut self, navcord: &mut NavcordStepper, step_count: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R> Navcorder<'a, R> {
|
impl<R: AccessRules> Navcorder for Layout<R> {
|
||||||
pub fn new(layout: &mut Layout<R>) -> Navcorder<R> {
|
fn start(
|
||||||
Navcorder { layout }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, R: AccessRules> Navcorder<'a, R> {
|
|
||||||
pub fn start(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: LayoutEdit,
|
recorder: LayoutEdit,
|
||||||
source: FixedDotIndex,
|
source: FixedDotIndex,
|
||||||
|
|
@ -46,21 +71,19 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
|
||||||
NavcordStepper::new(recorder, source, source_navvertex, width)
|
NavcordStepper::new(recorder, source, source_navvertex, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(
|
fn finish(
|
||||||
&mut self,
|
&mut self,
|
||||||
_navmesh: &Navmesh,
|
_navmesh: &Navmesh,
|
||||||
navcord: &mut NavcordStepper,
|
navcord: &mut NavcordStepper,
|
||||||
target: FixedDotIndex,
|
target: FixedDotIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<BandTermsegIndex, NavcorderException> {
|
) -> Result<BandTermsegIndex, NavcorderException> {
|
||||||
Ok(self
|
Ok(self.finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?)
|
||||||
.layout
|
|
||||||
.finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_requires(path[0] == navcord.path[0])]
|
#[debug_requires(path[0] == navcord.path[0])]
|
||||||
#[debug_ensures(ret.is_ok() -> navcord.path.len() == path.len())]
|
#[debug_ensures(ret.is_ok() -> navcord.path.len() == path.len())]
|
||||||
pub fn rework_path(
|
fn rework_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
navmesh: &Navmesh,
|
navmesh: &Navmesh,
|
||||||
navcord: &mut NavcordStepper,
|
navcord: &mut NavcordStepper,
|
||||||
|
|
@ -80,7 +103,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> navcord.path.len() == old(navcord.path.len() + path.len()))]
|
#[debug_ensures(ret.is_ok() -> navcord.path.len() == old(navcord.path.len() + path.len()))]
|
||||||
pub fn path(
|
fn path(
|
||||||
&mut self,
|
&mut self,
|
||||||
navmesh: &Navmesh,
|
navmesh: &Navmesh,
|
||||||
navcord: &mut NavcordStepper,
|
navcord: &mut NavcordStepper,
|
||||||
|
|
@ -89,7 +112,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
for (i, vertex) in path.iter().enumerate() {
|
for (i, vertex) in path.iter().enumerate() {
|
||||||
if let Err(err) = navcord.step(&mut NavcordStepContext {
|
if let Err(err) = navcord.step(&mut NavcordStepContext {
|
||||||
navcorder: self,
|
layout: self,
|
||||||
navmesh,
|
navmesh,
|
||||||
to: *vertex,
|
to: *vertex,
|
||||||
width,
|
width,
|
||||||
|
|
@ -103,7 +126,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
|
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
|
||||||
pub fn undo_path(&mut self, navcord: &mut NavcordStepper, step_count: usize) {
|
fn undo_path(&mut self, navcord: &mut NavcordStepper, step_count: usize) {
|
||||||
for _ in 0..step_count {
|
for _ in 0..step_count {
|
||||||
let _ = navcord.step_back(self);
|
let _ = navcord.step_back(self);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ impl RouteStepper {
|
||||||
let source_navvertex = navmesh.origin_navvertex();
|
let source_navvertex = navmesh.origin_navvertex();
|
||||||
let target = navmesh.destination();
|
let target = navmesh.destination();
|
||||||
|
|
||||||
let mut navcorder = Navcorder::new(router.layout_mut());
|
let layout = router.layout_mut();
|
||||||
let mut navcord = navcorder.start(recorder, source, source_navvertex, width);
|
let mut navcord = layout.start(recorder, source, source_navvertex, width);
|
||||||
|
|
||||||
let mut strategy = RouterAstarStrategy::new(navcorder, &mut navcord, target);
|
let mut strategy = RouterAstarStrategy::new(layout, &mut navcord, target);
|
||||||
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);
|
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);
|
||||||
let ghosts = vec![];
|
let ghosts = vec![];
|
||||||
let obstacles = vec![];
|
let obstacles = vec![];
|
||||||
|
|
@ -81,9 +81,9 @@ impl<'a, R: AccessRules> Step<Router<'a, R>, BandTermsegIndex> for RouteStepper
|
||||||
&mut self,
|
&mut self,
|
||||||
router: &mut Router<R>,
|
router: &mut Router<R>,
|
||||||
) -> Result<ControlFlow<BandTermsegIndex>, AstarError> {
|
) -> Result<ControlFlow<BandTermsegIndex>, AstarError> {
|
||||||
let navcorder = Navcorder::new(router.layout_mut());
|
let layout = router.layout_mut();
|
||||||
let target = self.astar.graph.destination();
|
let target = self.astar.graph.destination();
|
||||||
let mut strategy = RouterAstarStrategy::new(navcorder, &mut self.navcord, target);
|
let mut strategy = RouterAstarStrategy::new(layout, &mut self.navcord, target);
|
||||||
|
|
||||||
let result = match self.astar.step(&mut strategy)? {
|
let result = match self.astar.step(&mut strategy)? {
|
||||||
ControlFlow::Continue(..) => Ok(ControlFlow::Continue(())),
|
ControlFlow::Continue(..) => Ok(ControlFlow::Continue(())),
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ pub struct RouterOptions {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouterAstarStrategy<'a, R> {
|
pub struct RouterAstarStrategy<'a, R> {
|
||||||
pub navcorder: Navcorder<'a, R>,
|
pub layout: &'a mut Layout<R>,
|
||||||
pub navcord: &'a mut NavcordStepper,
|
pub navcord: &'a mut NavcordStepper,
|
||||||
pub target: FixedDotIndex,
|
pub target: FixedDotIndex,
|
||||||
pub probe_ghosts: Vec<PrimitiveShape>,
|
pub probe_ghosts: Vec<PrimitiveShape>,
|
||||||
|
|
@ -52,12 +52,12 @@ pub struct RouterAstarStrategy<'a, R> {
|
||||||
|
|
||||||
impl<'a, R> RouterAstarStrategy<'a, R> {
|
impl<'a, R> RouterAstarStrategy<'a, R> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
navcorder: Navcorder<'a, R>,
|
layout: &'a mut Layout<R>,
|
||||||
navcord: &'a mut NavcordStepper,
|
navcord: &'a mut NavcordStepper,
|
||||||
target: FixedDotIndex,
|
target: FixedDotIndex,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
navcorder,
|
layout,
|
||||||
navcord,
|
navcord,
|
||||||
target,
|
target,
|
||||||
probe_ghosts: vec![],
|
probe_ghosts: vec![],
|
||||||
|
|
@ -68,19 +68,15 @@ impl<'a, R> RouterAstarStrategy<'a, R> {
|
||||||
|
|
||||||
impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
|
impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
|
||||||
fn bihead_length(&self) -> f64 {
|
fn bihead_length(&self) -> f64 {
|
||||||
self.navcord
|
self.navcord.head.ref_(self.layout.drawing()).length()
|
||||||
.head
|
|
||||||
.ref_(self.navcorder.layout.drawing())
|
|
||||||
.length()
|
|
||||||
+ match self.navcord.head.face() {
|
+ match self.navcord.head.face() {
|
||||||
DotIndex::Fixed(..) => 0.0,
|
DotIndex::Fixed(..) => 0.0,
|
||||||
DotIndex::Loose(face) => self
|
DotIndex::Loose(face) => self
|
||||||
.navcorder
|
|
||||||
.layout
|
.layout
|
||||||
.drawing()
|
.drawing()
|
||||||
.guide()
|
.guide()
|
||||||
.rear_head(face)
|
.rear_head(face)
|
||||||
.ref_(self.navcorder.layout.drawing())
|
.ref_(self.layout.drawing())
|
||||||
.length(),
|
.length(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,11 +94,11 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
|
||||||
let new_path = tracker.reconstruct_path_to(vertex);
|
let new_path = tracker.reconstruct_path_to(vertex);
|
||||||
let width = self.navcord.width;
|
let width = self.navcord.width;
|
||||||
|
|
||||||
self.navcorder
|
self.layout
|
||||||
.rework_path(navmesh, self.navcord, &new_path[..], width)
|
.rework_path(navmesh, self.navcord, &new_path[..], width)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.navcorder
|
self.layout
|
||||||
.finish(navmesh, self.navcord, self.target, width)
|
.finish(navmesh, self.navcord, self.target, width)
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +112,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
|
||||||
|
|
||||||
let width = self.navcord.width;
|
let width = self.navcord.width;
|
||||||
let result = self.navcord.step(&mut NavcordStepContext {
|
let result = self.navcord.step(&mut NavcordStepContext {
|
||||||
navcorder: &mut self.navcorder,
|
layout: self.layout,
|
||||||
navmesh,
|
navmesh,
|
||||||
to: edge.target(),
|
to: edge.target(),
|
||||||
width,
|
width,
|
||||||
|
|
@ -154,16 +150,15 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_probe(&mut self, _navmesh: &Navmesh) {
|
fn remove_probe(&mut self, _navmesh: &Navmesh) {
|
||||||
self.navcord.step_back(&mut self.navcorder);
|
self.navcord.step_back(&mut self.layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {
|
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavvertexIndex) -> f64 {
|
||||||
let start_point = PrimitiveIndex::from(navmesh.node_weight(vertex).unwrap().node)
|
let start_point = PrimitiveIndex::from(navmesh.node_weight(vertex).unwrap().node)
|
||||||
.primitive(self.navcorder.layout.drawing())
|
.primitive(self.layout.drawing())
|
||||||
.shape()
|
.shape()
|
||||||
.center();
|
.center();
|
||||||
let end_point = self
|
let end_point = self
|
||||||
.navcorder
|
|
||||||
.layout
|
.layout
|
||||||
.drawing()
|
.drawing()
|
||||||
.primitive(self.target)
|
.primitive(self.target)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue