refactor: rename "trace" to "navcord", "tracer" to "navcorder"

Navcord stands for "navigation cord". I try to prefix anything that is
specific to the navmesh with the "nav-" prefix. I chose the word "cord"
as analogy to the terms "umbilical cord" (and by extension, umbilical
cable), and "power cord".

Calling this "trace" was misleading, as this term has other meanings
that are relevant to Topola: "trace" may refer to a debugging trace, and
more importantly, to a PCB track.

I've also shortened two comments that I found to mention the navcord as
"traces" during substitution.
This commit is contained in:
Mikolaj Wielgus 2024-10-10 03:00:27 +02:00
parent 911c974cfc
commit 8559734336
16 changed files with 219 additions and 216 deletions

View File

@ -1,6 +1,5 @@
//! Manages autorouting of ratlines in a layout, tracking status and processed //! Manages autorouting of ratlines in a layout, tracking status and processed
//! routing steps. Provides access to navigation meshes, traces, ghost shapes, //! routing steps.
//! and obstacles encountered during routing.
use petgraph::graph::EdgeIndex; use petgraph::graph::EdgeIndex;
@ -8,12 +7,14 @@ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex}, drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, route::RouteStepper, trace::TraceStepper, Router, RouterStatus}, router::{
navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router, RouterStatus,
},
stepper::Step, stepper::Step,
}; };
use super::{ use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
Autorouter, AutorouterError, AutorouterOptions, Autorouter, AutorouterError, AutorouterOptions,
}; };
@ -149,10 +150,10 @@ impl GetMaybeNavmesh for AutorouteExecutionStepper {
} }
} }
impl GetMaybeTrace for AutorouteExecutionStepper { impl GetMaybeNavcord for AutorouteExecutionStepper {
/// Retrieves an optional reference to the trace from the current route. /// Retrieves an optional reference to the navcord from the current route.
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
self.route.as_ref().map(|route| route.trace()) self.route.as_ref().map(|route| route.navcord())
} }
} }

View File

@ -1,7 +1,5 @@
//! Manages the comparison of detours between two ratlines, tracking their //! Manages the comparison of detours between two ratlines, tracking their
//! routing statuses and lengths. Facilitates stepwise processing of routing //! routing statuses and recording their lengths.
//! while providing access to navigation meshes, traces, ghost shapes, and
//! obstacles encountered.
use petgraph::graph::EdgeIndex; use petgraph::graph::EdgeIndex;
@ -10,13 +8,13 @@ use crate::{
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::{primitive::PrimitiveShape, shape::MeasureLength}, geometry::{primitive::PrimitiveShape, shape::MeasureLength},
graph::MakeRef, graph::MakeRef,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
stepper::Step, stepper::Step,
}; };
use super::{ use super::{
autoroute::{AutorouteExecutionStepper, AutorouteStatus}, autoroute::{AutorouteExecutionStepper, AutorouteStatus},
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
Autorouter, AutorouterError, AutorouterOptions, Autorouter, AutorouterError, AutorouterOptions,
}; };
@ -123,9 +121,9 @@ impl GetMaybeNavmesh for CompareDetoursExecutionStepper {
} }
} }
impl GetMaybeTrace for CompareDetoursExecutionStepper { impl GetMaybeNavcord for CompareDetoursExecutionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
self.autoroute.maybe_trace() self.autoroute.maybe_navcord()
} }
} }

View File

@ -25,7 +25,7 @@ pub enum Command {
MeasureLength(BandSelection), MeasureLength(BandSelection),
} }
#[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)] #[enum_dispatch(GetMaybeNavmesh, GetMaybeNavcord, GetGhosts, GetObstacles)]
pub enum ExecutionStepper { pub enum ExecutionStepper {
Autoroute(AutorouteExecutionStepper), Autoroute(AutorouteExecutionStepper),
PlaceVia(PlaceViaExecutionStepper), PlaceVia(PlaceViaExecutionStepper),

View File

@ -10,7 +10,7 @@ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
stepper::Step, stepper::Step,
}; };
@ -31,8 +31,8 @@ pub trait GetMaybeNavmesh {
} }
#[enum_dispatch] #[enum_dispatch]
pub trait GetMaybeTrace { pub trait GetMaybeNavcord {
fn maybe_trace(&self) -> Option<&TraceStepper>; fn maybe_navcord(&self) -> Option<&NavcordStepper>;
} }
#[enum_dispatch] #[enum_dispatch]

View File

@ -7,11 +7,11 @@ use crate::{
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::{primitive::PrimitiveShape, shape::MeasureLength as MeasureLengthTrait}, geometry::{primitive::PrimitiveShape, shape::MeasureLength as MeasureLengthTrait},
graph::MakeRef, graph::MakeRef,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
}; };
use super::{ use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
selection::BandSelection, selection::BandSelection,
Autorouter, AutorouterError, Autorouter, AutorouterError,
}; };
@ -61,8 +61,8 @@ impl GetMaybeNavmesh for MeasureLengthExecutionStepper {
} }
} }
impl GetMaybeTrace for MeasureLengthExecutionStepper { impl GetMaybeNavcord for MeasureLengthExecutionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
None None
} }
} }

View File

@ -7,11 +7,11 @@ use crate::{
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
layout::via::ViaWeight, layout::via::ViaWeight,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
}; };
use super::{ use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
Autorouter, AutorouterError, Autorouter, AutorouterError,
}; };
@ -49,8 +49,8 @@ impl GetMaybeNavmesh for PlaceViaExecutionStepper {
} }
} }
impl GetMaybeTrace for PlaceViaExecutionStepper { impl GetMaybeNavcord for PlaceViaExecutionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
None None
} }
} }

View File

@ -1,17 +1,14 @@
//! Provides functionality to remove bands from the layout in an //! Provides functionality to remove bands from the layout.
//! autorouting context. It defines a struct that interacts with the autorouter
//! to remove selected bands, and implements necessary traits for working
//! with navigation meshes, traces, and obstacles.
use crate::{ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
}; };
use super::{ use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
selection::BandSelection, selection::BandSelection,
Autorouter, AutorouterError, Autorouter, AutorouterError,
}; };
@ -58,8 +55,8 @@ impl GetMaybeNavmesh for RemoveBandsExecutionStepper {
} }
} }
impl GetMaybeTrace for RemoveBandsExecutionStepper { impl GetMaybeNavcord for RemoveBandsExecutionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
None None
} }
} }

View File

@ -3,13 +3,13 @@ use topola::{
autorouter::{ autorouter::{
execution::ExecutionStepper, execution::ExecutionStepper,
invoker::{ invoker::{
GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError, GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker, InvokerError,
InvokerStatus, InvokerStatus,
}, },
}, },
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
specctra::mesadata::SpecctraMesadata, specctra::mesadata::SpecctraMesadata,
stepper::{Abort, Step}, stepper::{Abort, Step},
}; };
@ -102,12 +102,12 @@ impl GetMaybeNavmesh for ActivityStepper {
} }
} }
impl GetMaybeTrace for ActivityStepper { impl GetMaybeNavcord for ActivityStepper {
/// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates. /// Implemented manually instead of with `enum_dispatch` because it doesn't work across crates.
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
match self { match self {
ActivityStepper::Interaction(interaction) => interaction.maybe_trace(), ActivityStepper::Interaction(interaction) => interaction.maybe_navcord(),
ActivityStepper::Execution(execution) => execution.maybe_trace(), ActivityStepper::Execution(execution) => execution.maybe_navcord(),
} }
} }
} }
@ -171,9 +171,9 @@ impl GetMaybeNavmesh for ActivityStepperWithStatus {
} }
} }
impl GetMaybeTrace for ActivityStepperWithStatus { impl GetMaybeNavcord for ActivityStepperWithStatus {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
self.activity.maybe_trace() self.activity.maybe_navcord()
} }
} }

View File

@ -1,9 +1,9 @@
use thiserror::Error; use thiserror::Error;
use topola::{ use topola::{
autorouter::invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh},
stepper::{Abort, Step}, stepper::{Abort, Step},
}; };
@ -63,8 +63,8 @@ impl GetMaybeNavmesh for InteractionStepper {
} }
} }
impl GetMaybeTrace for InteractionStepper { impl GetMaybeNavcord for InteractionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> { fn maybe_navcord(&self) -> Option<&NavcordStepper> {
todo!() todo!()
} }
} }

View File

@ -7,7 +7,7 @@ use rstar::{Envelope, AABB};
use topola::{ use topola::{
autorouter::{ autorouter::{
execution::Command, execution::Command,
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker},
}, },
drawing::{ drawing::{
graph::{MakePrimitive, PrimitiveIndex}, graph::{MakePrimitive, PrimitiveIndex},
@ -171,12 +171,12 @@ impl Viewport {
let stroke = 'blk: { let stroke = 'blk: {
if let (Some(source_pos), Some(target_pos)) = ( if let (Some(source_pos), Some(target_pos)) = (
activity.maybe_trace().map(|trace| activity.maybe_navcord().map(|navcord|
trace.path navcord.path
.iter() .iter()
.position(|node| *node == edge.source())).flatten(), .position(|node| *node == edge.source())).flatten(),
activity.maybe_trace().map(|trace| activity.maybe_navcord().map(|navcord|
trace.path navcord.path
.iter() .iter()
.position(|node| *node == edge.target())).flatten(), .position(|node| *node == edge.target())).flatten(),
) { ) {

View File

@ -1,9 +1,9 @@
pub mod astar; pub mod astar;
pub mod draw; pub mod draw;
pub mod navcord;
pub mod navcorder;
pub mod navmesh; pub mod navmesh;
pub mod route; pub mod route;
pub mod router; pub mod router;
pub mod trace;
pub mod tracer;
pub use router::*; pub use router::*;

View File

@ -11,23 +11,23 @@ use crate::drawing::{
use super::{ use super::{
draw::Draw, draw::Draw,
navcorder::{Navcorder, NavcorderException},
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex}, navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
tracer::{Tracer, TracerException},
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct TraceStepper { pub struct NavcordStepper {
pub path: Vec<NavvertexIndex>, pub path: Vec<NavvertexIndex>,
pub head: Head, pub head: Head,
pub width: f64, pub width: f64,
} }
impl TraceStepper { impl NavcordStepper {
pub fn new( pub fn new(
source: FixedDotIndex, source: FixedDotIndex,
source_navvertex: NavvertexIndex, source_navvertex: NavvertexIndex,
width: f64, width: f64,
) -> TraceStepper { ) -> NavcordStepper {
Self { Self {
path: vec![source_navvertex], path: vec![source_navvertex],
head: BareHead { face: source }.into(), head: BareHead { face: source }.into(),
@ -37,47 +37,47 @@ impl TraceStepper {
fn wrap( fn wrap(
&mut self, &mut self,
tracer: &mut Tracer<impl AccessRules>, navcorder: &mut Navcorder<impl AccessRules>,
navmesh: &Navmesh, navmesh: &Navmesh,
head: Head, head: Head,
around: NavvertexIndex, around: NavvertexIndex,
width: f64, width: f64,
) -> Result<CaneHead, TracerException> { ) -> Result<CaneHead, NavcorderException> {
let cw = self let cw = self
.maybe_cw(navmesh, around) .maybe_cw(navmesh, around)
.ok_or(TracerException::CannotWrap)?; .ok_or(NavcorderException::CannotWrap)?;
match self.binavvertex(navmesh, around) { match self.binavvertex(navmesh, around) {
BinavvertexNodeIndex::FixedDot(dot) => { BinavvertexNodeIndex::FixedDot(dot) => {
self.wrap_around_fixed_dot(tracer, head, dot, cw, width) self.wrap_around_fixed_dot(navcorder, 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(tracer, head, loose_bend, cw, width) self.wrap_around_loose_bend(navcorder, head, loose_bend, cw, width)
} }
} }
} }
fn wrap_around_fixed_dot( fn wrap_around_fixed_dot(
&mut self, &mut self,
tracer: &mut Tracer<impl AccessRules>, navcorder: &mut Navcorder<impl AccessRules>,
head: Head, head: Head,
around: FixedDotIndex, around: FixedDotIndex,
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<CaneHead, TracerException> { ) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(tracer.layout).cane_around_dot(head, around, cw, width)?) Ok(Draw::new(navcorder.layout).cane_around_dot(head, around, cw, width)?)
} }
fn wrap_around_loose_bend( fn wrap_around_loose_bend(
&mut self, &mut self,
tracer: &mut Tracer<impl AccessRules>, navcorder: &mut Navcorder<impl AccessRules>,
head: Head, head: Head,
around: LooseBendIndex, around: LooseBendIndex,
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<CaneHead, TracerException> { ) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(tracer.layout).cane_around_bend(head, around.into(), cw, width)?) Ok(Draw::new(navcorder.layout).cane_around_bend(head, around.into(), cw, width)?)
} }
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex { fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
@ -93,24 +93,24 @@ impl TraceStepper {
} }
} }
pub struct TraceStepContext<'a: 'b, 'b, R: AccessRules> { pub struct NavcordStepContext<'a: 'b, 'b, R: AccessRules> {
pub tracer: &'b mut Tracer<'a, R>, pub navcorder: &'b mut Navcorder<'a, R>,
pub navmesh: &'b Navmesh, pub navmesh: &'b Navmesh,
pub to: NavvertexIndex, pub to: NavvertexIndex,
pub width: f64, pub width: f64,
} }
impl TraceStepper { 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<'a, 'b, R: AccessRules>(
&mut self, &mut self,
input: &mut TraceStepContext<'a, 'b, R>, input: &mut NavcordStepContext<'a, 'b, R>,
) -> Result<(), TracerException> { ) -> Result<(), NavcorderException> {
self.head = self self.head = self
.wrap( .wrap(
input.tracer, input.navcorder,
input.navmesh, input.navmesh,
self.head, self.head,
input.to, input.to,
@ -125,10 +125,10 @@ impl TraceStepper {
#[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<'a, R: AccessRules>(
&mut self, &mut self,
tracer: &mut Tracer<'a, R>, navcorder: &mut Navcorder<'a, R>,
) -> Result<(), TracerException> { ) -> Result<(), NavcorderException> {
if let Head::Cane(head) = self.head { if let Head::Cane(head) = self.head {
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap(); self.head = Draw::new(navcorder.layout).undo_cane(head).unwrap();
} else { } else {
panic!(); panic!();
} }

102
src/router/navcorder.rs Normal file
View File

@ -0,0 +1,102 @@
use contracts_try::{debug_ensures, debug_requires};
use thiserror::Error;
use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout,
};
use super::{
draw::{Draw, DrawException},
navcord::{NavcordStepContext, NavcordStepper},
navmesh::{Navmesh, NavvertexIndex},
};
#[derive(Error, Debug, Clone, Copy)]
pub enum NavcorderException {
#[error(transparent)]
CannotDraw(#[from] DrawException),
#[error("cannot wrap")]
CannotWrap,
}
#[derive(Debug)]
pub struct Navcorder<'a, R: AccessRules> {
pub layout: &'a mut Layout<R>,
}
impl<'a, R: AccessRules> Navcorder<'a, R> {
pub fn new(layout: &mut Layout<R>) -> Navcorder<R> {
Navcorder { layout }
}
pub fn start(
&mut self,
source: FixedDotIndex,
source_navvertex: NavvertexIndex,
width: f64,
) -> NavcordStepper {
NavcordStepper::new(source, source_navvertex, width)
}
pub fn finish(
&mut self,
_navmesh: &Navmesh,
navcord: &mut NavcordStepper,
target: FixedDotIndex,
width: f64,
) -> Result<BandTermsegIndex, NavcorderException> {
Ok(Draw::new(self.layout).finish_in_dot(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(
&mut self,
navmesh: &Navmesh,
navcord: &mut NavcordStepper,
path: &[NavvertexIndex],
width: f64,
) -> Result<(), NavcorderException> {
let prefix_length = navcord
.path
.iter()
.zip(path)
.take_while(|(v1, v2)| v1 == v2)
.count();
let length = navcord.path.len();
self.undo_path(navcord, length - prefix_length);
self.path(navmesh, navcord, &path[prefix_length..], width)
}
#[debug_ensures(ret.is_ok() -> navcord.path.len() == old(navcord.path.len() + path.len()))]
pub fn path(
&mut self,
navmesh: &Navmesh,
navcord: &mut NavcordStepper,
path: &[NavvertexIndex],
width: f64,
) -> Result<(), NavcorderException> {
for (i, vertex) in path.iter().enumerate() {
if let Err(err) = navcord.step(&mut NavcordStepContext {
navcorder: self,
navmesh,
to: *vertex,
width,
}) {
self.undo_path(navcord, i);
return Err(err);
}
}
Ok(())
}
#[debug_ensures(navcord.path.len() == old(navcord.path.len() - step_count))]
pub fn undo_path(&mut self, navcord: &mut NavcordStepper, step_count: usize) {
for _ in 0..step_count {
let _ = navcord.step_back(self);
}
}
}

View File

@ -5,9 +5,9 @@ use crate::{
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
router::{ router::{
astar::{Astar, AstarError, AstarStatus}, astar::{Astar, AstarError, AstarStatus},
navcord::NavcordStepper,
navcorder::Navcorder,
navmesh::{Navmesh, NavmeshError}, navmesh::{Navmesh, NavmeshError},
trace::TraceStepper,
tracer::Tracer,
Router, RouterAstarStrategy, RouterStatus, Router, RouterAstarStrategy, RouterStatus,
}, },
stepper::Step, stepper::Step,
@ -15,7 +15,7 @@ use crate::{
pub struct RouteStepper { pub struct RouteStepper {
astar: Astar<Navmesh, f64>, astar: Astar<Navmesh, f64>,
trace: TraceStepper, navcord: NavcordStepper,
ghosts: Vec<PrimitiveShape>, ghosts: Vec<PrimitiveShape>,
obstacles: Vec<PrimitiveIndex>, obstacles: Vec<PrimitiveIndex>,
} }
@ -40,17 +40,17 @@ impl RouteStepper {
let source_navvertex = navmesh.origin_navvertex(); let source_navvertex = navmesh.origin_navvertex();
let target = navmesh.destination(); let target = navmesh.destination();
let mut tracer = Tracer::new(router.layout_mut()); let mut navcorder = Navcorder::new(router.layout_mut());
let mut trace = tracer.start(source, source_navvertex, width); let mut navcord = navcorder.start(source, source_navvertex, width);
let mut strategy = RouterAstarStrategy::new(tracer, &mut trace, target); let mut strategy = RouterAstarStrategy::new(navcorder, &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![];
Self { Self {
astar, astar,
trace, navcord,
ghosts, ghosts,
obstacles, obstacles,
} }
@ -60,8 +60,8 @@ impl RouteStepper {
&self.astar.graph &self.astar.graph
} }
pub fn trace(&self) -> &TraceStepper { pub fn navcord(&self) -> &NavcordStepper {
&self.trace &self.navcord
} }
pub fn ghosts(&self) -> &[PrimitiveShape] { pub fn ghosts(&self) -> &[PrimitiveShape] {
@ -77,9 +77,9 @@ impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, AstarError, BandTerms
for RouteStepper for RouteStepper
{ {
fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, AstarError> { fn step(&mut self, router: &mut Router<R>) -> Result<RouterStatus, AstarError> {
let tracer = Tracer::new(router.layout_mut()); let navcorder = Navcorder::new(router.layout_mut());
let target = self.astar.graph.destination(); let target = self.astar.graph.destination();
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target); let mut strategy = RouterAstarStrategy::new(navcorder, &mut self.navcord, target);
let result = match self.astar.step(&mut strategy)? { let result = match self.astar.step(&mut strategy)? {
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => { AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {

View File

@ -23,10 +23,10 @@ use crate::{
use super::{ use super::{
astar::{AstarStrategy, PathTracker}, astar::{AstarStrategy, PathTracker},
draw::DrawException, draw::DrawException,
navcord::{NavcordStepContext, NavcordStepper},
navcorder::{Navcorder, NavcorderException},
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex}, navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex},
route::RouteStepper, route::RouteStepper,
trace::{TraceStepContext, TraceStepper},
tracer::{Tracer, TracerException},
}; };
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
@ -53,18 +53,22 @@ impl TryInto<BandTermsegIndex> for RouterStatus {
#[derive(Debug)] #[derive(Debug)]
pub struct RouterAstarStrategy<'a, R: AccessRules> { pub struct RouterAstarStrategy<'a, R: AccessRules> {
pub tracer: Tracer<'a, R>, pub navcorder: Navcorder<'a, R>,
pub trace: &'a mut TraceStepper, pub navcord: &'a mut NavcordStepper,
pub target: FixedDotIndex, pub target: FixedDotIndex,
pub probe_ghosts: Vec<PrimitiveShape>, pub probe_ghosts: Vec<PrimitiveShape>,
pub probe_obstacles: Vec<PrimitiveIndex>, pub probe_obstacles: Vec<PrimitiveIndex>,
} }
impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> { impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
pub fn new(tracer: Tracer<'a, R>, trace: &'a mut TraceStepper, target: FixedDotIndex) -> Self { pub fn new(
navcorder: Navcorder<'a, R>,
navcord: &'a mut NavcordStepper,
target: FixedDotIndex,
) -> Self {
Self { Self {
tracer, navcorder,
trace, navcord,
target, target,
probe_ghosts: vec![], probe_ghosts: vec![],
probe_obstacles: vec![], probe_obstacles: vec![],
@ -72,16 +76,19 @@ impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
} }
fn bihead_length(&self) -> f64 { fn bihead_length(&self) -> f64 {
self.trace.head.ref_(self.tracer.layout.drawing()).length() self.navcord
+ match self.trace.head.face() { .head
.ref_(self.navcorder.layout.drawing())
.length()
+ match self.navcord.head.face() {
DotIndex::Fixed(..) => 0.0, DotIndex::Fixed(..) => 0.0,
DotIndex::Loose(face) => self DotIndex::Loose(face) => self
.tracer .navcorder
.layout .layout
.drawing() .drawing()
.guide() .guide()
.rear_head(face) .rear_head(face)
.ref_(self.tracer.layout.drawing()) .ref_(self.navcorder.layout.drawing())
.length(), .length(),
} }
} }
@ -97,14 +104,14 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
tracker: &PathTracker<Navmesh>, tracker: &PathTracker<Navmesh>,
) -> Option<BandTermsegIndex> { ) -> Option<BandTermsegIndex> {
let new_path = tracker.reconstruct_path_to(vertex); let new_path = tracker.reconstruct_path_to(vertex);
let width = self.trace.width; let width = self.navcord.width;
self.tracer self.navcorder
.rework_path(navmesh, self.trace, &new_path[..], width) .rework_path(navmesh, self.navcord, &new_path[..], width)
.unwrap(); .unwrap();
self.tracer self.navcorder
.finish(navmesh, self.trace, self.target, width) .finish(navmesh, self.navcord, self.target, width)
.ok() .ok()
} }
@ -115,9 +122,9 @@ 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.navcord.width;
let result = self.trace.step(&mut TraceStepContext { let result = self.navcord.step(&mut NavcordStepContext {
tracer: &mut self.tracer, navcorder: &mut self.navcorder,
navmesh, navmesh,
to: edge.target(), to: edge.target(),
width, width,
@ -128,7 +135,7 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
match result { match result {
Ok(..) => Some(probe_length), Ok(..) => Some(probe_length),
Err(err) => { Err(err) => {
if let TracerException::CannotDraw(draw_err) = err { if let NavcorderException::CannotDraw(draw_err) = err {
let layout_err = match draw_err { let layout_err = match draw_err {
DrawException::NoTangents(..) => return None, DrawException::NoTangents(..) => return None,
DrawException::CannotFinishIn(.., layout_err) => layout_err, DrawException::CannotFinishIn(.., layout_err) => layout_err,
@ -155,16 +162,16 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
} }
fn remove_probe(&mut self, _navmesh: &Navmesh) { fn remove_probe(&mut self, _navmesh: &Navmesh) {
self.trace.step_back(&mut self.tracer); self.navcord.step_back(&mut self.navcorder);
} }
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.tracer.layout.drawing()) .primitive(self.navcorder.layout.drawing())
.shape() .shape()
.center(); .center();
let end_point = self let end_point = self
.tracer .navcorder
.layout .layout
.drawing() .drawing()
.primitive(self.target) .primitive(self.target)

View File

@ -1,102 +0,0 @@
use contracts_try::{debug_ensures, debug_requires};
use thiserror::Error;
use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout,
};
use super::{
draw::{Draw, DrawException},
navmesh::{Navmesh, NavvertexIndex},
trace::{TraceStepContext, TraceStepper},
};
#[derive(Error, Debug, Clone, Copy)]
pub enum TracerException {
#[error(transparent)]
CannotDraw(#[from] DrawException),
#[error("cannot wrap")]
CannotWrap,
}
#[derive(Debug)]
pub struct Tracer<'a, R: AccessRules> {
pub layout: &'a mut Layout<R>,
}
impl<'a, R: AccessRules> Tracer<'a, R> {
pub fn new(layout: &mut Layout<R>) -> Tracer<R> {
Tracer { layout }
}
pub fn start(
&mut self,
source: FixedDotIndex,
source_navvertex: NavvertexIndex,
width: f64,
) -> TraceStepper {
TraceStepper::new(source, source_navvertex, width)
}
pub fn finish(
&mut self,
_navmesh: &Navmesh,
trace: &mut TraceStepper,
target: FixedDotIndex,
width: f64,
) -> Result<BandTermsegIndex, TracerException> {
Ok(Draw::new(self.layout).finish_in_dot(trace.head, target, width)?)
}
#[debug_requires(path[0] == trace.path[0])]
#[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())]
pub fn rework_path(
&mut self,
navmesh: &Navmesh,
trace: &mut TraceStepper,
path: &[NavvertexIndex],
width: f64,
) -> Result<(), TracerException> {
let prefix_length = trace
.path
.iter()
.zip(path)
.take_while(|(v1, v2)| v1 == v2)
.count();
let length = trace.path.len();
self.undo_path(trace, length - prefix_length);
self.path(navmesh, trace, &path[prefix_length..], width)
}
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + path.len()))]
pub fn path(
&mut self,
navmesh: &Navmesh,
trace: &mut TraceStepper,
path: &[NavvertexIndex],
width: f64,
) -> Result<(), TracerException> {
for (i, vertex) in path.iter().enumerate() {
if let Err(err) = trace.step(&mut TraceStepContext {
tracer: self,
navmesh,
to: *vertex,
width,
}) {
self.undo_path(trace, i);
return Err(err);
}
}
Ok(())
}
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
pub fn undo_path(&mut self, trace: &mut TraceStepper, step_count: usize) {
for _ in 0..step_count {
let _ = trace.step_back(self);
}
}
}