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},
rules::AccessRules,
},
layout::LayoutEdit,
layout::{Layout, LayoutEdit},
};
use super::{
draw::Draw,
navcorder::{Navcorder, NavcorderException},
navcorder::NavcorderException,
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
};
@ -56,7 +56,7 @@ impl NavcordStepper {
fn wrap(
&mut self,
navcorder: &mut Navcorder<impl AccessRules>,
layout: &mut Layout<impl AccessRules>,
navmesh: &Navmesh,
head: Head,
around: NavvertexIndex,
@ -68,39 +68,35 @@ impl NavcordStepper {
match self.binavvertex(navmesh, around) {
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::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(
&mut self,
navcorder: &mut Navcorder<impl AccessRules>,
layout: &mut Layout<impl AccessRules>,
head: Head,
around: FixedDotIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, NavcorderException> {
Ok(navcorder
.layout
.cane_around_dot(&mut self.recorder, head, around, cw, width)?)
Ok(layout.cane_around_dot(&mut self.recorder, head, around, cw, width)?)
}
fn wrap_around_loose_bend(
&mut self,
navcorder: &mut Navcorder<impl AccessRules>,
layout: &mut Layout<impl AccessRules>,
head: Head,
around: LooseBendIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, NavcorderException> {
Ok(navcorder
.layout
.cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?)
Ok(layout.cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?)
}
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
@ -116,9 +112,9 @@ impl NavcordStepper {
}
}
pub struct NavcordStepContext<'a: 'b, 'b, R> {
pub navcorder: &'b mut Navcorder<'a, R>,
pub navmesh: &'b Navmesh,
pub struct NavcordStepContext<'a, R> {
pub layout: &'a mut Layout<R>,
pub navmesh: &'a Navmesh,
pub to: NavvertexIndex,
pub width: f64,
}
@ -127,13 +123,13 @@ impl NavcordStepper {
#[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<'a, 'b, R: AccessRules>(
pub fn step<R: AccessRules>(
&mut self,
input: &mut NavcordStepContext<'a, 'b, R>,
input: &mut NavcordStepContext<'_, R>,
) -> Result<(), NavcorderException> {
self.head = self
.wrap(
input.navcorder,
input.layout,
input.navmesh,
self.head,
input.to,
@ -146,15 +142,12 @@ impl NavcordStepper {
}
#[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,
navcorder: &mut Navcorder<'a, R>,
layout: &mut Layout<R>,
) -> Result<(), NavcorderException> {
if let Head::Cane(head) = self.head {
self.head = navcorder
.layout
.undo_cane(&mut self.recorder, head)
.unwrap();
self.head = layout.undo_cane(&mut self.recorder, head).unwrap();
} else {
panic!();
}

View File

@ -24,19 +24,44 @@ pub enum NavcorderException {
CannotWrap,
}
#[derive(Debug)]
pub struct Navcorder<'a, R> {
pub layout: &'a mut Layout<R>,
pub trait Navcorder {
fn start(
&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> {
pub fn new(layout: &mut Layout<R>) -> Navcorder<R> {
Navcorder { layout }
}
}
impl<'a, R: AccessRules> Navcorder<'a, R> {
pub fn start(
impl<R: AccessRules> Navcorder for Layout<R> {
fn start(
&mut self,
recorder: LayoutEdit,
source: FixedDotIndex,
@ -46,21 +71,19 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
NavcordStepper::new(recorder, source, source_navvertex, width)
}
pub fn finish(
fn finish(
&mut self,
_navmesh: &Navmesh,
navcord: &mut NavcordStepper,
target: FixedDotIndex,
width: f64,
) -> Result<BandTermsegIndex, NavcorderException> {
Ok(self
.layout
.finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?)
Ok(self.finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?)
}
#[debug_requires(path[0] == navcord.path[0])]
#[debug_ensures(ret.is_ok() -> navcord.path.len() == path.len())]
pub fn rework_path(
fn rework_path(
&mut self,
navmesh: &Navmesh,
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()))]
pub fn path(
fn path(
&mut self,
navmesh: &Navmesh,
navcord: &mut NavcordStepper,
@ -89,7 +112,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
) -> Result<(), NavcorderException> {
for (i, vertex) in path.iter().enumerate() {
if let Err(err) = navcord.step(&mut NavcordStepContext {
navcorder: self,
layout: self,
navmesh,
to: *vertex,
width,
@ -103,7 +126,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
}
#[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 {
let _ = navcord.step_back(self);
}

View File

@ -53,10 +53,10 @@ impl RouteStepper {
let source_navvertex = navmesh.origin_navvertex();
let target = navmesh.destination();
let mut navcorder = Navcorder::new(router.layout_mut());
let mut navcord = navcorder.start(recorder, source, source_navvertex, width);
let layout = router.layout_mut();
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 ghosts = vec![];
let obstacles = vec![];
@ -81,9 +81,9 @@ impl<'a, R: AccessRules> Step<Router<'a, R>, BandTermsegIndex> for RouteStepper
&mut self,
router: &mut Router<R>,
) -> Result<ControlFlow<BandTermsegIndex>, AstarError> {
let navcorder = Navcorder::new(router.layout_mut());
let layout = router.layout_mut();
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)? {
ControlFlow::Continue(..) => Ok(ControlFlow::Continue(())),

View File

@ -43,7 +43,7 @@ pub struct RouterOptions {
#[derive(Debug)]
pub struct RouterAstarStrategy<'a, R> {
pub navcorder: Navcorder<'a, R>,
pub layout: &'a mut Layout<R>,
pub navcord: &'a mut NavcordStepper,
pub target: FixedDotIndex,
pub probe_ghosts: Vec<PrimitiveShape>,
@ -52,12 +52,12 @@ pub struct RouterAstarStrategy<'a, R> {
impl<'a, R> RouterAstarStrategy<'a, R> {
pub fn new(
navcorder: Navcorder<'a, R>,
layout: &'a mut Layout<R>,
navcord: &'a mut NavcordStepper,
target: FixedDotIndex,
) -> Self {
Self {
navcorder,
layout,
navcord,
target,
probe_ghosts: vec![],
@ -68,19 +68,15 @@ impl<'a, R> RouterAstarStrategy<'a, R> {
impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
fn bihead_length(&self) -> f64 {
self.navcord
.head
.ref_(self.navcorder.layout.drawing())
.length()
self.navcord.head.ref_(self.layout.drawing()).length()
+ match self.navcord.head.face() {
DotIndex::Fixed(..) => 0.0,
DotIndex::Loose(face) => self
.navcorder
.layout
.drawing()
.guide()
.rear_head(face)
.ref_(self.navcorder.layout.drawing())
.ref_(self.layout.drawing())
.length(),
}
}
@ -98,11 +94,11 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
let new_path = tracker.reconstruct_path_to(vertex);
let width = self.navcord.width;
self.navcorder
self.layout
.rework_path(navmesh, self.navcord, &new_path[..], width)
.unwrap();
self.navcorder
self.layout
.finish(navmesh, self.navcord, self.target, width)
.ok()
}
@ -116,7 +112,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
let width = self.navcord.width;
let result = self.navcord.step(&mut NavcordStepContext {
navcorder: &mut self.navcorder,
layout: self.layout,
navmesh,
to: edge.target(),
width,
@ -154,16 +150,15 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
}
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 {
let start_point = PrimitiveIndex::from(navmesh.node_weight(vertex).unwrap().node)
.primitive(self.navcorder.layout.drawing())
.primitive(self.layout.drawing())
.shape()
.center();
let end_point = self
.navcorder
.layout
.drawing()
.primitive(self.target)