feat(router/navcord): Make it possible to visit leap navnodes

Closes https://codeberg.org/topola/topola/issues/121
This commit is contained in:
Mikolaj Wielgus 2025-05-23 01:46:45 +02:00
parent a27b263288
commit aef5c6471e
4 changed files with 19 additions and 11 deletions

View File

@ -18,7 +18,7 @@ use crate::{
use super::{
draw::Draw,
navcorder::{Navcorder, NavcorderException},
navmesh::{NavigableNodeIndex, Navmesh, NavnodeIndex},
navmesh::{NavigableNodeIndex, Navmesh, NavnodeIndex, NavnodeWeight},
};
/// The `Navcord` is a data structure that holds the movable non-borrowing data
@ -106,17 +106,20 @@ impl Navcord {
navmesh: &Navmesh,
to: NavnodeIndex,
) -> Result<(), NavcorderException> {
if to == navmesh.destination_navnode() {
let to_node_weight = navmesh.node_weight(to).unwrap();
if to == navmesh.destination_navnode() {
let NavigableNodeIndex::FixedDot(to_dot) = to_node_weight.node() else {
unreachable!();
};
self.final_termseg = Some(layout.finish(navmesh, self, to_dot).unwrap());
self.final_termseg = Some(layout.finish(navmesh, self, to_dot)?);
// NOTE: We don't update the head here because there is currently
// no head variant that consists only of a seg, and I'm not sure if
// there should be one.
} else if matches!(to_node_weight, NavnodeWeight::Leap(..)) {
// Nothing to do beyond pushing the navnode onto the path.
} else {
self.head = self.wrap(layout, navmesh, self.head, to)?.into();
}
@ -134,10 +137,15 @@ impl Navcord {
pub fn step_back<R: AccessRules>(
&mut self,
layout: &mut Layout<R>,
navmesh: &Navmesh,
) -> Result<(), NavcorderException> {
let last_node_weight = navmesh.node_weight(*self.path.last().unwrap());
if let Some(final_termseg) = self.final_termseg {
layout.remove_termseg(&mut self.recorder, final_termseg);
self.final_termseg = None;
} else if matches!(last_node_weight, Some(NavnodeWeight::Leap(..))) {
// Nothing to do beyond popping the navnode from the path.
} else {
if let Head::Cane(head) = self.head {
self.head = layout.undo_cane(&mut self.recorder, head).unwrap();

View File

@ -54,7 +54,7 @@ pub trait Navcorder {
path: &[NavnodeIndex],
) -> Result<(), NavcorderException>;
fn undo_path(&mut self, navcord: &mut Navcord, step_count: usize);
fn undo_path(&mut self, navmesh: &Navmesh, navcord: &mut Navcord, step_count: usize);
}
impl<R: AccessRules> Navcorder for Layout<R> {
@ -93,7 +93,7 @@ impl<R: AccessRules> Navcorder for Layout<R> {
.count();
let length = navcord.path.len();
self.undo_path(navcord, length - prefix_length);
self.undo_path(navmesh, navcord, length - prefix_length);
self.path(navmesh, navcord, &path[prefix_length..])
}
@ -106,7 +106,7 @@ impl<R: AccessRules> Navcorder for Layout<R> {
) -> Result<(), NavcorderException> {
for (i, vertex) in path.iter().enumerate() {
if let Err(err) = navcord.step_to(self, navmesh, *vertex) {
self.undo_path(navcord, i);
self.undo_path(navmesh, navcord, i);
return Err(err);
}
}
@ -115,9 +115,9 @@ impl<R: AccessRules> Navcorder for Layout<R> {
}
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
fn undo_path(&mut self, navcord: &mut Navcord, step_count: usize) {
fn undo_path(&mut self, navmesh: &Navmesh, navcord: &mut Navcord, step_count: usize) {
for _ in 0..step_count {
let _ = navcord.step_back(self);
let _ = navcord.step_back(self, navmesh);
}
}
}

View File

@ -90,7 +90,7 @@ impl<R: AccessRules> Step<Router<'_, R>, BandTermsegIndex> for RouteStepper {
// NOTE(fogti): The 1 instead 0 is because the first element in the path
// is the source navnode. See also: `NavcordStepper::new`.
for _ in 1..self.navcord.path.len() {
self.navcord.step_back(layout);
self.navcord.step_back(layout, &self.astar.graph);
}
Err(e)
}

View File

@ -136,8 +136,8 @@ impl<R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex> for RouterAst
}
}
fn remove_probe(&mut self, _navmesh: &Navmesh) {
self.navcord.step_back(self.layout);
fn remove_probe(&mut self, navmesh: &Navmesh) {
self.navcord.step_back(self.layout, navmesh);
}
fn estimate_cost(&mut self, navmesh: &Navmesh, vertex: NavnodeIndex) -> f64 {