refactor(router::navcorder): turn Navcorder into a trait

This commit is contained in:
Ellen Emilia Anna Zscheile 2025-02-01 23:33:02 +01:00 committed by mikolaj
parent 1d11011133
commit 90544c12ed
4 changed files with 75 additions and 64 deletions

View File

@ -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!();
} }

View File

@ -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);
} }

View File

@ -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(())),

View File

@ -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)