router: split out `Trace` to its own file and give it its own methods

We'll be following this pattern:
* `Autorouter` - `Autoroute`,
* `Router` - `Route` (not yet done),
* `Tracer` - `Trace`.

Agent nouns (ending with -er) denote the object that holds large and
"unportable" parts of the state (such as `Board`, `Layout`, `Drawing`,
`Geometry`), while verbs (ending with -e) denote holders of other, more
"portable" parts of the state.
This commit is contained in:
Mikolaj Wielgus 2024-06-27 23:56:39 +02:00
parent 664bbee0b9
commit 4fa97509e4
7 changed files with 137 additions and 111 deletions

View File

@ -14,8 +14,8 @@ pub struct Autoroute {
impl Autoroute {
pub fn new(
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
autorouter: &mut Autorouter<impl MesadataTrait>,
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
) -> Result<Self, AutorouterError> {
let mut ratlines_iter = Box::new(ratlines.into_iter());

View File

@ -60,7 +60,7 @@ impl<M: MesadataTrait> Autorouter<M> {
}
pub fn autoroute_walk(&mut self, selection: &Selection) -> Result<Autoroute, AutorouterError> {
Autoroute::new(self.selected_ratlines(selection), self)
Autoroute::new(self, self.selected_ratlines(selection))
}
pub fn undo_autoroute(&mut self, selection: &Selection) {

View File

@ -38,12 +38,12 @@ pub enum Head {
#[derive(Debug, Clone, Copy)]
pub struct BareHead {
pub dot: FixedDotIndex,
pub face: FixedDotIndex,
}
impl HeadTrait for BareHead {
fn face(&self) -> DotIndex {
self.dot.into()
self.face.into()
}
}
@ -233,7 +233,7 @@ impl<'a, CW: Copy, R: RulesTrait> Guide<'a, CW, R> {
pub fn head(&self, face: DotIndex) -> Head {
match face {
DotIndex::Fixed(dot) => BareHead { dot }.into(),
DotIndex::Fixed(dot) => BareHead { face: dot }.into(),
DotIndex::Loose(dot) => self.cane_head(dot).into(),
}
}

View File

@ -2,6 +2,7 @@ pub mod astar;
pub mod draw;
pub mod navmesh;
mod router;
pub mod trace;
pub mod tracer;
pub use router::*;

View File

@ -25,7 +25,8 @@ use crate::{
BinavvertexNodeIndex, Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex,
NavvertexWeight,
},
tracer::{Trace, Tracer},
trace::Trace,
tracer::Tracer,
},
};
@ -118,13 +119,13 @@ impl<'a, R: RulesTrait> AstarStrategy<Navmesh, f64, BandFirstSegIndex>
let width = self.trace.width;
let result = self
.tracer
.step(navmesh, &mut self.trace, edge.target(), width);
.trace
.step(&mut self.tracer, navmesh, edge.target(), width);
let probe_length = self.bihead_length() - prev_bihead_length;
if result.is_ok() {
self.tracer.undo_step(navmesh, &mut self.trace);
self.trace.undo_step(&mut self.tracer);
Some(probe_length)
} else {
None
@ -169,7 +170,7 @@ impl Router {
let target = navmesh.target();
let mut tracer = Tracer::new(layout);
let mut trace = tracer.start(&navmesh, source, source_navvertex, width);
let mut trace = tracer.start(source, source_navvertex, width);
let mut strategy = RouterAstarStrategy::new(tracer, &mut trace, target);
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);

118
src/router/trace.rs Normal file
View File

@ -0,0 +1,118 @@
use contracts::debug_ensures;
use petgraph::data::DataMap;
use crate::{
drawing::{
bend::LooseBendIndex,
dot::FixedDotIndex,
graph::PrimitiveIndex,
guide::{BareHead, CaneHead, Head},
rules::RulesTrait,
},
router::{
draw::Draw,
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
tracer::{Tracer, TracerException},
},
};
#[derive(Debug)]
pub struct Trace {
pub path: Vec<NavvertexIndex>,
pub head: Head,
pub width: f64,
}
impl Trace {
pub fn new(source: FixedDotIndex, source_navvertex: NavvertexIndex, width: f64) -> Trace {
Self {
path: vec![source_navvertex],
head: BareHead { face: source }.into(),
width,
}
}
#[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(
&mut self,
tracer: &mut Tracer<impl RulesTrait>,
navmesh: &Navmesh,
to: NavvertexIndex,
width: f64,
) -> Result<(), TracerException> {
self.head = self.wrap(tracer, navmesh, self.head, to, width)?.into();
self.path.push(to);
Ok::<(), TracerException>(())
}
#[debug_ensures(self.path.len() == old(self.path.len() - 1))]
pub fn undo_step(&mut self, tracer: &mut Tracer<impl RulesTrait>) {
if let Head::Cane(head) = self.head {
self.head = Draw::new(tracer.layout).undo_cane(head).unwrap();
} else {
panic!();
}
self.path.pop();
}
fn wrap(
&mut self,
tracer: &mut Tracer<impl RulesTrait>,
navmesh: &Navmesh,
head: Head,
around: NavvertexIndex,
width: f64,
) -> Result<CaneHead, TracerException> {
let cw = self
.maybe_cw(navmesh, around)
.ok_or(TracerException::CannotWrap)?;
match self.binavvertex(navmesh, around) {
BinavvertexNodeIndex::FixedDot(dot) => {
self.wrap_around_fixed_dot(tracer, head, dot, cw, width)
}
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
BinavvertexNodeIndex::LooseBend(loose_bend) => {
self.wrap_around_loose_bend(tracer, head, loose_bend, cw, width)
}
}
}
fn wrap_around_fixed_dot(
&mut self,
tracer: &mut Tracer<impl RulesTrait>,
head: Head,
around: FixedDotIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(tracer.layout).cane_around_dot(head, around.into(), cw, width)?)
}
fn wrap_around_loose_bend(
&mut self,
tracer: &mut Tracer<impl RulesTrait>,
head: Head,
around: LooseBendIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(tracer.layout).cane_around_bend(head, around.into(), cw, width)?)
}
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
navmesh.node_weight(navvertex).unwrap().node
}
fn primitive(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> PrimitiveIndex {
self.binavvertex(navmesh, navvertex).into()
}
fn maybe_cw(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> Option<bool> {
navmesh.node_weight(navvertex).unwrap().maybe_cw
}
}

View File

@ -18,6 +18,7 @@ use crate::{
router::{
draw::{Draw, DrawException},
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex, NavvertexWeight},
trace::Trace,
},
};
@ -29,13 +30,6 @@ pub enum TracerException {
CannotWrap,
}
#[derive(Debug)]
pub struct Trace {
pub path: Vec<NavvertexIndex>,
pub head: Head,
pub width: f64,
}
#[derive(Debug)]
pub struct Tracer<'a, R: RulesTrait> {
pub layout: &'a mut Layout<R>,
@ -48,16 +42,11 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
pub fn start(
&mut self,
_navmesh: &Navmesh,
source: FixedDotIndex,
source_navvertex: NavvertexIndex,
width: f64,
) -> Trace {
Trace {
path: vec![source_navvertex],
head: BareHead { dot: source }.into(),
width,
}
Trace::new(source, source_navvertex, width)
}
pub fn finish(
@ -87,7 +76,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
.count();
let length = trace.path.len();
self.undo_path(navmesh, trace, length - prefix_length);
self.undo_path(trace, length - prefix_length);
Ok::<(), TracerException>(self.path(navmesh, trace, &path[prefix_length..], width)?)
}
@ -100,8 +89,8 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
width: f64,
) -> Result<(), TracerException> {
for (i, vertex) in path.iter().enumerate() {
if let Err(err) = self.step(navmesh, trace, *vertex, width) {
self.undo_path(navmesh, trace, i);
if let Err(err) = trace.step(self, navmesh, *vertex, width) {
self.undo_path(trace, i);
return Err(err.into());
}
}
@ -110,92 +99,9 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
}
#[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))]
pub fn undo_path(&mut self, navmesh: &Navmesh, trace: &mut Trace, step_count: usize) {
pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) {
for _ in 0..step_count {
self.undo_step(navmesh, trace);
trace.undo_step(self);
}
}
#[debug_ensures(ret.is_ok() -> matches!(trace.head, Head::Cane(..)))]
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + 1))]
#[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))]
pub fn step(
&mut self,
navmesh: &Navmesh,
trace: &mut Trace,
to: NavvertexIndex,
width: f64,
) -> Result<(), TracerException> {
trace.head = self.wrap(navmesh, trace.head, to, width)?.into();
trace.path.push(to);
Ok::<(), TracerException>(())
}
fn wrap(
&mut self,
navmesh: &Navmesh,
head: Head,
around: NavvertexIndex,
width: f64,
) -> Result<CaneHead, TracerException> {
let cw = self
.maybe_cw(navmesh, around)
.ok_or(TracerException::CannotWrap)?;
match self.binavvertex(navmesh, around) {
BinavvertexNodeIndex::FixedDot(dot) => {
self.wrap_around_fixed_dot(navmesh, head, dot, cw, width)
}
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
BinavvertexNodeIndex::LooseBend(loose_bend) => {
self.wrap_around_loose_bend(navmesh, head, loose_bend, cw, width)
}
}
}
fn wrap_around_fixed_dot(
&mut self,
_navmesh: &Navmesh,
head: Head,
around: FixedDotIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(self.layout).cane_around_dot(head, around.into(), cw, width)?)
}
fn wrap_around_loose_bend(
&mut self,
_navmesh: &Navmesh,
head: Head,
around: LooseBendIndex,
cw: bool,
width: f64,
) -> Result<CaneHead, TracerException> {
Ok(Draw::new(self.layout).cane_around_bend(head, around.into(), cw, width)?)
}
#[debug_ensures(trace.path.len() == old(trace.path.len() - 1))]
pub fn undo_step(&mut self, _navmesh: &Navmesh, trace: &mut Trace) {
if let Head::Cane(head) = trace.head {
trace.head = Draw::new(self.layout).undo_cane(head).unwrap();
} else {
panic!();
}
trace.path.pop();
}
fn maybe_cw(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> Option<bool> {
navmesh.node_weight(navvertex).unwrap().maybe_cw
}
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
navmesh.node_weight(navvertex).unwrap().node
}
fn primitive(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> PrimitiveIndex {
self.binavvertex(navmesh, navvertex).into()
}
}