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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,14 @@
//! Provides functionality to remove bands from the layout in an
//! 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.
//! Provides functionality to remove bands from the layout.
use crate::{
board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper},
router::{navcord::NavcordStepper, navmesh::Navmesh},
};
use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
selection::BandSelection,
Autorouter, AutorouterError,
};
@ -58,8 +55,8 @@ impl GetMaybeNavmesh for RemoveBandsExecutionStepper {
}
}
impl GetMaybeTrace for RemoveBandsExecutionStepper {
fn maybe_trace(&self) -> Option<&TraceStepper> {
impl GetMaybeNavcord for RemoveBandsExecutionStepper {
fn maybe_navcord(&self) -> Option<&NavcordStepper> {
None
}
}

View File

@ -3,13 +3,13 @@ use topola::{
autorouter::{
execution::ExecutionStepper,
invoker::{
GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles, Invoker, InvokerError,
GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker, InvokerError,
InvokerStatus,
},
},
drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::TraceStepper},
router::{navcord::NavcordStepper, navmesh::Navmesh},
specctra::mesadata::SpecctraMesadata,
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.
fn maybe_trace(&self) -> Option<&TraceStepper> {
fn maybe_navcord(&self) -> Option<&NavcordStepper> {
match self {
ActivityStepper::Interaction(interaction) => interaction.maybe_trace(),
ActivityStepper::Execution(execution) => execution.maybe_trace(),
ActivityStepper::Interaction(interaction) => interaction.maybe_navcord(),
ActivityStepper::Execution(execution) => execution.maybe_navcord(),
}
}
}
@ -171,9 +171,9 @@ impl GetMaybeNavmesh for ActivityStepperWithStatus {
}
}
impl GetMaybeTrace for ActivityStepperWithStatus {
fn maybe_trace(&self) -> Option<&TraceStepper> {
self.activity.maybe_trace()
impl GetMaybeNavcord for ActivityStepperWithStatus {
fn maybe_navcord(&self) -> Option<&NavcordStepper> {
self.activity.maybe_navcord()
}
}

View File

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

View File

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

View File

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

View File

@ -11,23 +11,23 @@ use crate::drawing::{
use super::{
draw::Draw,
navcorder::{Navcorder, NavcorderException},
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
tracer::{Tracer, TracerException},
};
#[derive(Debug)]
pub struct TraceStepper {
pub struct NavcordStepper {
pub path: Vec<NavvertexIndex>,
pub head: Head,
pub width: f64,
}
impl TraceStepper {
impl NavcordStepper {
pub fn new(
source: FixedDotIndex,
source_navvertex: NavvertexIndex,
width: f64,
) -> TraceStepper {
) -> NavcordStepper {
Self {
path: vec![source_navvertex],
head: BareHead { face: source }.into(),
@ -37,47 +37,47 @@ impl TraceStepper {
fn wrap(
&mut self,
tracer: &mut Tracer<impl AccessRules>,
navcorder: &mut Navcorder<impl AccessRules>,
navmesh: &Navmesh,
head: Head,
around: NavvertexIndex,
width: f64,
) -> Result<CaneHead, TracerException> {
) -> Result<CaneHead, NavcorderException> {
let cw = self
.maybe_cw(navmesh, around)
.ok_or(TracerException::CannotWrap)?;
.ok_or(NavcorderException::CannotWrap)?;
match self.binavvertex(navmesh, around) {
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::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(
&mut self,
tracer: &mut Tracer<impl AccessRules>,
navcorder: &mut Navcorder<impl AccessRules>,
head: Head,
around: FixedDotIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(tracer.layout).cane_around_dot(head, around, cw, width)?)
) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(navcorder.layout).cane_around_dot(head, around, cw, width)?)
}
fn wrap_around_loose_bend(
&mut self,
tracer: &mut Tracer<impl AccessRules>,
navcorder: &mut Navcorder<impl AccessRules>,
head: Head,
around: LooseBendIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(tracer.layout).cane_around_bend(head, around.into(), cw, width)?)
) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(navcorder.layout).cane_around_bend(head, around.into(), cw, width)?)
}
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
@ -93,24 +93,24 @@ impl TraceStepper {
}
}
pub struct TraceStepContext<'a: 'b, 'b, R: AccessRules> {
pub tracer: &'b mut Tracer<'a, R>,
pub struct NavcordStepContext<'a: 'b, 'b, R: AccessRules> {
pub navcorder: &'b mut Navcorder<'a, R>,
pub navmesh: &'b Navmesh,
pub to: NavvertexIndex,
pub width: f64,
}
impl TraceStepper {
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>(
&mut self,
input: &mut TraceStepContext<'a, 'b, R>,
) -> Result<(), TracerException> {
input: &mut NavcordStepContext<'a, 'b, R>,
) -> Result<(), NavcorderException> {
self.head = self
.wrap(
input.tracer,
input.navcorder,
input.navmesh,
self.head,
input.to,
@ -125,10 +125,10 @@ impl TraceStepper {
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
pub fn step_back<'a, R: AccessRules>(
&mut self,
tracer: &mut Tracer<'a, R>,
) -> Result<(), TracerException> {
navcorder: &mut Navcorder<'a, R>,
) -> Result<(), NavcorderException> {
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 {
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,
router::{
astar::{Astar, AstarError, AstarStatus},
navcord::NavcordStepper,
navcorder::Navcorder,
navmesh::{Navmesh, NavmeshError},
trace::TraceStepper,
tracer::Tracer,
Router, RouterAstarStrategy, RouterStatus,
},
stepper::Step,
@ -15,7 +15,7 @@ use crate::{
pub struct RouteStepper {
astar: Astar<Navmesh, f64>,
trace: TraceStepper,
navcord: NavcordStepper,
ghosts: Vec<PrimitiveShape>,
obstacles: Vec<PrimitiveIndex>,
}
@ -40,17 +40,17 @@ impl RouteStepper {
let source_navvertex = navmesh.origin_navvertex();
let target = navmesh.destination();
let mut tracer = Tracer::new(router.layout_mut());
let mut trace = tracer.start(source, source_navvertex, width);
let mut navcorder = Navcorder::new(router.layout_mut());
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 ghosts = vec![];
let obstacles = vec![];
Self {
astar,
trace,
navcord,
ghosts,
obstacles,
}
@ -60,8 +60,8 @@ impl RouteStepper {
&self.astar.graph
}
pub fn trace(&self) -> &TraceStepper {
&self.trace
pub fn navcord(&self) -> &NavcordStepper {
&self.navcord
}
pub fn ghosts(&self) -> &[PrimitiveShape] {
@ -77,9 +77,9 @@ impl<'a, R: AccessRules> Step<Router<'a, R>, RouterStatus, AstarError, BandTerms
for RouteStepper
{
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 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)? {
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => {

View File

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