fix(autorouter,router): actually propagate the edit out of route steppers

I forgot to do this earlier, and didn't notice because I didn't test
it. There are still a few changes to be done before recording and edit
applying is functional.
This commit is contained in:
Mikolaj Wielgus 2024-12-02 05:56:37 +01:00
parent 0760fb2da3
commit fe8fd3909f
8 changed files with 84 additions and 39 deletions

View File

@ -35,6 +35,7 @@ derive-getters.workspace = true
enum_dispatch = "0.3.13" enum_dispatch = "0.3.13"
geo.workspace = true geo.workspace = true
petgraph.workspace = true petgraph.workspace = true
replace_with = "0.1.7"
rstar.workspace = true rstar.workspace = true
serde.workspace = true serde.workspace = true
spade.workspace = true spade.workspace = true

View File

@ -63,6 +63,7 @@ impl AutorouteExecutionStepper {
ratlines_iter, ratlines_iter,
options, options,
route: Some(router.route( route: Some(router.route(
LayoutEdit::new(),
origin, origin,
destination, destination,
options.router_options.routed_band_width, options.router_options.routed_band_width,
@ -123,14 +124,22 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
Router::new(autorouter.board.layout_mut(), self.options.router_options); Router::new(autorouter.board.layout_mut(), self.options.router_options);
self.curr_ratline = Some(new_ratline); self.curr_ratline = Some(new_ratline);
let recorder = if let Some(taken_route) = self.route.take() {
let (_astar, navcord, ..) = taken_route.dissolve();
navcord.recorder
} else {
LayoutEdit::new()
};
self.route = Some(router.route( self.route = Some(router.route(
recorder,
source, source,
target, target,
self.options.router_options.routed_band_width, self.options.router_options.routed_band_width,
)?); )?);
} else { } else {
self.curr_ratline = None; self.curr_ratline = None;
//return Ok(AutorouteStatus::Finished);
} }
Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed( Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed(

View File

@ -47,6 +47,7 @@ impl PointrouteExecutionStepper {
Ok(Self { Ok(Self {
point, point,
route: router.route( route: router.route(
LayoutEdit::new(),
origin, origin,
destination, destination,
options.router_options.routed_band_width, options.router_options.routed_band_width,

View File

@ -31,6 +31,9 @@ pub enum DrawException {
CannotWrapAround(GearIndex, #[source] DrawingException), CannotWrapAround(GearIndex, #[source] DrawingException),
} }
/// This struct is a simple wrapper whose sole purpose is to have a separate
/// file for the router module's routines for drawing and erasing the primitives
/// to pull out or contract the currently routed band.
pub struct Draw<'a, R: AccessRules> { pub struct Draw<'a, R: AccessRules> {
layout: &'a mut Layout<R>, layout: &'a mut Layout<R>,
} }
@ -48,6 +51,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
pub fn finish_in_dot( pub fn finish_in_dot(
&mut self, &mut self,
recorder: &mut LayoutEdit,
head: Head, head: Head,
into: FixedDotIndex, into: FixedDotIndex,
width: f64, width: f64,
@ -57,7 +61,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
.head_into_dot_segment(&head, into, width) .head_into_dot_segment(&head, into, width)
.map_err(Into::<DrawException>::into)?; .map_err(Into::<DrawException>::into)?;
let head = self let head = self
.extend_head(head, tangent.start_point()) .extend_head(recorder, head, tangent.start_point())
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
let layer = head.face().primitive(self.layout.drawing()).layer(); let layer = head.face().primitive(self.layout.drawing()).layer();
let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net(); let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net();
@ -66,7 +70,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
DotIndex::Fixed(dot) => BandTermsegIndex::Straight( DotIndex::Fixed(dot) => BandTermsegIndex::Straight(
self.layout self.layout
.add_lone_loose_seg( .add_lone_loose_seg(
&mut LayoutEdit::new(), recorder,
dot, dot,
into, into,
LoneLooseSegWeight { LoneLooseSegWeight {
@ -80,7 +84,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
DotIndex::Loose(dot) => BandTermsegIndex::Bended( DotIndex::Loose(dot) => BandTermsegIndex::Bended(
self.layout self.layout
.add_seq_loose_seg( .add_seq_loose_seg(
&mut LayoutEdit::new(), recorder,
into.into(), into.into(),
dot, dot,
SeqLooseSegWeight { SeqLooseSegWeight {
@ -98,6 +102,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
pub fn cane_around_dot( pub fn cane_around_dot(
&mut self, &mut self,
recorder: &mut LayoutEdit,
head: Head, head: Head,
around: FixedDotIndex, around: FixedDotIndex,
cw: bool, cw: bool,
@ -110,6 +115,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
.guide() .guide()
.head_around_dot_offset(&head, around.into(), width); .head_around_dot_offset(&head, around.into(), width);
self.cane_around( self.cane_around(
recorder,
head, head,
around.into(), around.into(),
tangent.start_point(), tangent.start_point(),
@ -125,6 +131,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
pub fn cane_around_bend( pub fn cane_around_bend(
&mut self, &mut self,
recorder: &mut LayoutEdit,
head: Head, head: Head,
around: BendIndex, around: BendIndex,
cw: bool, cw: bool,
@ -136,6 +143,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
let offset = self.guide().head_around_bend_offset(&head, around, width); let offset = self.guide().head_around_bend_offset(&head, around, width);
self.cane_around( self.cane_around(
recorder,
head, head,
around.into(), around.into(),
tangent.start_point(), tangent.start_point(),
@ -151,6 +159,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
fn cane_around( fn cane_around(
&mut self, &mut self,
recorder: &mut LayoutEdit,
head: Head, head: Head,
around: GearIndex, around: GearIndex,
from: Point, from: Point,
@ -159,15 +168,19 @@ impl<'a, R: AccessRules> Draw<'a, R> {
width: f64, width: f64,
offset: f64, offset: f64,
) -> Result<CaneHead, DrawingException> { ) -> Result<CaneHead, DrawingException> {
let head = self.extend_head(head, from)?; let head = self.extend_head(recorder, head, from)?;
self.cane(head, around, to, cw, width, offset) self.cane(recorder, head, around, to, cw, width, offset)
} }
#[debug_ensures(self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, Infringement> { fn extend_head(
&mut self,
recorder: &mut LayoutEdit,
head: Head,
to: Point,
) -> Result<Head, Infringement> {
if let Head::Cane(head) = head { if let Head::Cane(head) = head {
self.layout self.layout.move_dot(recorder, head.face.into(), to)?;
.move_dot(&mut LayoutEdit::new(), head.face.into(), to)?;
Ok(Head::Cane(head)) Ok(Head::Cane(head))
} else { } else {
Ok(head) Ok(head)
@ -178,6 +191,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
fn cane( fn cane(
&mut self, &mut self,
recorder: &mut LayoutEdit,
head: Head, head: Head,
around: GearIndex, around: GearIndex,
to: Point, to: Point,
@ -188,7 +202,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
let layer = head.face().primitive(self.layout.drawing()).layer(); let layer = head.face().primitive(self.layout.drawing()).layer();
let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net(); let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net();
let cane = self.layout.insert_cane( let cane = self.layout.insert_cane(
&mut LayoutEdit::new(), recorder,
head.face(), head.face(),
around, around,
LooseDotWeight { LooseDotWeight {

View File

@ -1,12 +1,15 @@
use contracts_try::debug_ensures; use contracts_try::debug_ensures;
use petgraph::data::DataMap; use petgraph::data::DataMap;
use crate::drawing::{ use crate::{
bend::LooseBendIndex, drawing::{
dot::FixedDotIndex, bend::LooseBendIndex,
graph::PrimitiveIndex, dot::FixedDotIndex,
head::{BareHead, CaneHead, Head}, graph::PrimitiveIndex,
rules::AccessRules, head::{BareHead, CaneHead, Head},
rules::AccessRules,
},
layout::LayoutEdit,
}; };
use super::{ use super::{
@ -15,13 +18,14 @@ use super::{
navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex}, navmesh::{BinavvertexNodeIndex, Navmesh, NavvertexIndex},
}; };
/// The navcord is a structure that holds the movable non-borrowing data of the /// The navcord (stepper) is a structure that holds the movable non-borrowing
/// currently running routing process. /// data of the currently running routing process.
/// ///
/// The name "navcord" is a shortening of "navigation cord", by analogy to /// The name "navcord" is a shortening of "navigation cord", by analogy to
/// "navmesh" being a shortening of "navigation mesh". /// "navmesh" being a shortening of "navigation mesh".
#[derive(Debug)] #[derive(Debug)]
pub struct NavcordStepper { pub struct NavcordStepper {
pub recorder: LayoutEdit,
/// The currently attempted path. /// The currently attempted path.
pub path: Vec<NavvertexIndex>, pub path: Vec<NavvertexIndex>,
/// Head of the routed band. /// Head of the routed band.
@ -33,11 +37,13 @@ pub struct NavcordStepper {
impl NavcordStepper { impl NavcordStepper {
/// Creates a new navcord. /// Creates a new navcord.
pub fn new( pub fn new(
recorder: LayoutEdit,
source: FixedDotIndex, source: FixedDotIndex,
source_navvertex: NavvertexIndex, source_navvertex: NavvertexIndex,
width: f64, width: f64,
) -> NavcordStepper { ) -> NavcordStepper {
Self { Self {
recorder,
path: vec![source_navvertex], path: vec![source_navvertex],
head: BareHead { face: source }.into(), head: BareHead { face: source }.into(),
width, width,
@ -75,7 +81,13 @@ impl NavcordStepper {
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<CaneHead, NavcorderException> { ) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(navcorder.layout).cane_around_dot(head, around, cw, width)?) Ok(Draw::new(navcorder.layout).cane_around_dot(
&mut self.recorder,
head,
around,
cw,
width,
)?)
} }
fn wrap_around_loose_bend( fn wrap_around_loose_bend(
@ -86,7 +98,13 @@ impl NavcordStepper {
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<CaneHead, NavcorderException> { ) -> Result<CaneHead, NavcorderException> {
Ok(Draw::new(navcorder.layout).cane_around_bend(head, around.into(), cw, width)?) Ok(Draw::new(navcorder.layout).cane_around_bend(
&mut self.recorder,
head,
around.into(),
cw,
width,
)?)
} }
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex { fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {

View File

@ -3,7 +3,7 @@ use thiserror::Error;
use crate::{ use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
layout::Layout, layout::{Layout, LayoutEdit},
}; };
use super::{ use super::{
@ -32,11 +32,12 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
pub fn start( pub fn start(
&mut self, &mut self,
recorder: LayoutEdit,
source: FixedDotIndex, source: FixedDotIndex,
source_navvertex: NavvertexIndex, source_navvertex: NavvertexIndex,
width: f64, width: f64,
) -> NavcordStepper { ) -> NavcordStepper {
NavcordStepper::new(source, source_navvertex, width) NavcordStepper::new(recorder, source, source_navvertex, width)
} }
pub fn finish( pub fn finish(
@ -46,7 +47,12 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
target: FixedDotIndex, target: FixedDotIndex,
width: f64, width: f64,
) -> Result<BandTermsegIndex, NavcorderException> { ) -> Result<BandTermsegIndex, NavcorderException> {
Ok(Draw::new(self.layout).finish_in_dot(navcord.head, target, width)?) Ok(Draw::new(self.layout).finish_in_dot(
&mut navcord.recorder,
navcord.head,
target,
width,
)?)
} }
#[debug_requires(path[0] == navcord.path[0])] #[debug_requires(path[0] == navcord.path[0])]

View File

@ -1,10 +1,13 @@
use std::ops::ControlFlow; use std::ops::ControlFlow;
use derive_getters::{Dissolve, Getters};
use crate::{ use crate::{
drawing::{ drawing::{
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules, band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
}, },
geometry::primitive::PrimitiveShape, geometry::primitive::PrimitiveShape,
layout::LayoutEdit,
router::{ router::{
astar::{Astar, AstarError}, astar::{Astar, AstarError},
navcord::NavcordStepper, navcord::NavcordStepper,
@ -15,7 +18,9 @@ use crate::{
stepper::Step, stepper::Step,
}; };
#[derive(Getters, Dissolve)]
pub struct RouteStepper { pub struct RouteStepper {
#[getter(skip)]
astar: Astar<Navmesh, f64>, astar: Astar<Navmesh, f64>,
navcord: NavcordStepper, navcord: NavcordStepper,
ghosts: Vec<PrimitiveShape>, ghosts: Vec<PrimitiveShape>,
@ -25,16 +30,18 @@ pub struct RouteStepper {
impl RouteStepper { impl RouteStepper {
pub fn new( pub fn new(
router: &mut Router<impl AccessRules>, router: &mut Router<impl AccessRules>,
recorder: LayoutEdit,
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
width: f64, width: f64,
) -> Result<Self, NavmeshError> { ) -> Result<Self, NavmeshError> {
let navmesh = Navmesh::new(router.layout(), from, to, router.options().clone())?; let navmesh = Navmesh::new(router.layout(), from, to, router.options().clone())?;
Ok(Self::new_from_navmesh(router, navmesh, width)) Ok(Self::new_from_navmesh(router, recorder, navmesh, width))
} }
pub fn new_from_navmesh( pub fn new_from_navmesh(
router: &mut Router<impl AccessRules>, router: &mut Router<impl AccessRules>,
recorder: LayoutEdit,
navmesh: Navmesh, navmesh: Navmesh,
width: f64, width: f64,
) -> Self { ) -> Self {
@ -43,7 +50,7 @@ impl RouteStepper {
let target = navmesh.destination(); let target = navmesh.destination();
let mut navcorder = Navcorder::new(router.layout_mut()); let mut navcorder = Navcorder::new(router.layout_mut());
let mut navcord = navcorder.start(source, source_navvertex, width); let mut navcord = navcorder.start(recorder, source, source_navvertex, width);
let mut strategy = RouterAstarStrategy::new(navcorder, &mut navcord, 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);
@ -61,18 +68,6 @@ impl RouteStepper {
pub fn navmesh(&self) -> &Navmesh { pub fn navmesh(&self) -> &Navmesh {
&self.astar.graph &self.astar.graph
} }
pub fn navcord(&self) -> &NavcordStepper {
&self.navcord
}
pub fn ghosts(&self) -> &[PrimitiveShape] {
&self.ghosts
}
pub fn obstacles(&self) -> &[PrimitiveIndex] {
&self.obstacles
}
} }
impl<'a, R: AccessRules> Step<Router<'a, R>, BandTermsegIndex> for RouteStepper { impl<'a, R: AccessRules> Step<Router<'a, R>, BandTermsegIndex> for RouteStepper {

View File

@ -18,7 +18,7 @@ use crate::{
shape::{AccessShape, MeasureLength}, shape::{AccessShape, MeasureLength},
}, },
graph::{GetPetgraphIndex, MakeRef}, graph::{GetPetgraphIndex, MakeRef},
layout::Layout, layout::{Layout, LayoutEdit},
}; };
use super::{ use super::{
@ -182,11 +182,12 @@ impl<'a, R: AccessRules> Router<'a, R> {
pub fn route( pub fn route(
&mut self, &mut self,
recorder: LayoutEdit,
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
width: f64, width: f64,
) -> Result<RouteStepper, NavmeshError> { ) -> Result<RouteStepper, NavmeshError> {
RouteStepper::new(self, from, to, width) RouteStepper::new(self, recorder, from, to, width)
} }
pub fn layout_mut(&mut self) -> &mut Layout<R> { pub fn layout_mut(&mut self) -> &mut Layout<R> {