mirror of https://codeberg.org/topola/topola.git
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:
parent
664bbee0b9
commit
4fa97509e4
|
|
@ -14,8 +14,8 @@ pub struct Autoroute {
|
||||||
|
|
||||||
impl Autoroute {
|
impl Autoroute {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
|
|
||||||
autorouter: &mut Autorouter<impl MesadataTrait>,
|
autorouter: &mut Autorouter<impl MesadataTrait>,
|
||||||
|
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
|
||||||
) -> Result<Self, AutorouterError> {
|
) -> Result<Self, AutorouterError> {
|
||||||
let mut ratlines_iter = Box::new(ratlines.into_iter());
|
let mut ratlines_iter = Box::new(ratlines.into_iter());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ impl<M: MesadataTrait> Autorouter<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn autoroute_walk(&mut self, selection: &Selection) -> Result<Autoroute, AutorouterError> {
|
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) {
|
pub fn undo_autoroute(&mut self, selection: &Selection) {
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ pub enum Head {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BareHead {
|
pub struct BareHead {
|
||||||
pub dot: FixedDotIndex,
|
pub face: FixedDotIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeadTrait for BareHead {
|
impl HeadTrait for BareHead {
|
||||||
fn face(&self) -> DotIndex {
|
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 {
|
pub fn head(&self, face: DotIndex) -> Head {
|
||||||
match face {
|
match face {
|
||||||
DotIndex::Fixed(dot) => BareHead { dot }.into(),
|
DotIndex::Fixed(dot) => BareHead { face: dot }.into(),
|
||||||
DotIndex::Loose(dot) => self.cane_head(dot).into(),
|
DotIndex::Loose(dot) => self.cane_head(dot).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ pub mod astar;
|
||||||
pub mod draw;
|
pub mod draw;
|
||||||
pub mod navmesh;
|
pub mod navmesh;
|
||||||
mod router;
|
mod router;
|
||||||
|
pub mod trace;
|
||||||
pub mod tracer;
|
pub mod tracer;
|
||||||
|
|
||||||
pub use router::*;
|
pub use router::*;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ use crate::{
|
||||||
BinavvertexNodeIndex, Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex,
|
BinavvertexNodeIndex, Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexIndex,
|
||||||
NavvertexWeight,
|
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 width = self.trace.width;
|
||||||
let result = self
|
let result = self
|
||||||
.tracer
|
.trace
|
||||||
.step(navmesh, &mut self.trace, edge.target(), width);
|
.step(&mut self.tracer, navmesh, edge.target(), width);
|
||||||
|
|
||||||
let probe_length = self.bihead_length() - prev_bihead_length;
|
let probe_length = self.bihead_length() - prev_bihead_length;
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
self.tracer.undo_step(navmesh, &mut self.trace);
|
self.trace.undo_step(&mut self.tracer);
|
||||||
Some(probe_length)
|
Some(probe_length)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -169,7 +170,7 @@ impl Router {
|
||||||
let target = navmesh.target();
|
let target = navmesh.target();
|
||||||
|
|
||||||
let mut tracer = Tracer::new(layout);
|
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 mut strategy = RouterAstarStrategy::new(tracer, &mut trace, target);
|
||||||
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);
|
let astar = Astar::new(navmesh, source_navvertex, &mut strategy);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ use crate::{
|
||||||
router::{
|
router::{
|
||||||
draw::{Draw, DrawException},
|
draw::{Draw, DrawException},
|
||||||
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex, NavvertexWeight},
|
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex, NavvertexWeight},
|
||||||
|
trace::Trace,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -29,13 +30,6 @@ pub enum TracerException {
|
||||||
CannotWrap,
|
CannotWrap,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Trace {
|
|
||||||
pub path: Vec<NavvertexIndex>,
|
|
||||||
pub head: Head,
|
|
||||||
pub width: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Tracer<'a, R: RulesTrait> {
|
pub struct Tracer<'a, R: RulesTrait> {
|
||||||
pub layout: &'a mut Layout<R>,
|
pub layout: &'a mut Layout<R>,
|
||||||
|
|
@ -48,16 +42,11 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
||||||
|
|
||||||
pub fn start(
|
pub fn start(
|
||||||
&mut self,
|
&mut self,
|
||||||
_navmesh: &Navmesh,
|
|
||||||
source: FixedDotIndex,
|
source: FixedDotIndex,
|
||||||
source_navvertex: NavvertexIndex,
|
source_navvertex: NavvertexIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Trace {
|
) -> Trace {
|
||||||
Trace {
|
Trace::new(source, source_navvertex, width)
|
||||||
path: vec![source_navvertex],
|
|
||||||
head: BareHead { dot: source }.into(),
|
|
||||||
width,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(
|
pub fn finish(
|
||||||
|
|
@ -87,7 +76,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
let length = trace.path.len();
|
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)?)
|
Ok::<(), TracerException>(self.path(navmesh, trace, &path[prefix_length..], width)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,8 +89,8 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<(), TracerException> {
|
) -> Result<(), TracerException> {
|
||||||
for (i, vertex) in path.iter().enumerate() {
|
for (i, vertex) in path.iter().enumerate() {
|
||||||
if let Err(err) = self.step(navmesh, trace, *vertex, width) {
|
if let Err(err) = trace.step(self, navmesh, *vertex, width) {
|
||||||
self.undo_path(navmesh, trace, i);
|
self.undo_path(trace, i);
|
||||||
return Err(err.into());
|
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))]
|
#[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 {
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue