From 26631ed6cdd886346ac17bf3392e05b99e3c150c Mon Sep 17 00:00:00 2001 From: Alain Emilia Anna Zscheile Date: Fri, 3 Jan 2025 03:41:13 +0100 Subject: [PATCH] refactor(router::draw): Draw should be an extension/wrapper trait around RecordingLayout --- src/layout/layout.rs | 18 +++ src/router/draw.rs | 289 ++++++++++++++++++++-------------------- src/router/navcord.rs | 28 ++-- src/router/navcorder.rs | 3 +- 4 files changed, 174 insertions(+), 164 deletions(-) diff --git a/src/layout/layout.rs b/src/layout/layout.rs index d26fdd9..31bf2b7 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -16,6 +16,7 @@ use crate::{ dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, gear::GearIndex, graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight}, + guide::Guide, primitive::MakePrimitiveShape, rules::AccessRules, seg::{ @@ -191,6 +192,10 @@ impl Layout { self.drawing.rules_mut() } + pub fn guide(&self) -> Guide { + Guide::new(&self.drawing) + } + pub fn poly(&self, index: GenericIndex) -> Poly { Poly::new(index, self) } @@ -200,11 +205,24 @@ impl Layout { } } +// this is a hack, but it allows us to not needing as much boilerplate for delegations +impl core::ops::Deref for RecordingLayout<'_, R> { + type Target = Layout; + + fn deref(&self) -> &Layout { + self.layout + } +} + impl RecordingLayout<'_, R> { fn recording_drawing(&mut self) -> RecordingDrawing<'_, CompoundWeight, R> { self.layout.drawing.recording(self.recorder) } + pub fn rules_mut(&mut self) -> &mut R { + self.layout.drawing.rules_mut() + } + /// Insert [`Cane`] object into the [`Layout`] pub fn insert_cane( &mut self, diff --git a/src/router/draw.rs b/src/router/draw.rs index 0329847..61b429c 100644 --- a/src/router/draw.rs +++ b/src/router/draw.rs @@ -18,9 +18,9 @@ use crate::{ primitive::GetOtherJoint, rules::AccessRules, seg::{LoneLooseSegWeight, SeqLooseSegWeight}, - DrawingException, Infringement, + Drawing, DrawingException, Infringement, }, - layout::{Layout, LayoutEdit}, + layout::{CompoundWeight, Layout, LayoutEdit, RecordingLayout}, math::{Circle, NoTangents}, }; @@ -35,27 +35,47 @@ pub enum DrawException { CannotWrapAround(GearIndex, #[source] DrawingException), } -/// This struct is a simple wrapper whose sole purpose is to have a separate +/// This trait 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> { - layout: &'a mut Layout, +pub trait Draw { + fn start(&mut self, from: LooseDotIndex) -> Head; + + fn finish_in_dot( + &mut self, + head: Head, + into: FixedDotIndex, + width: f64, + ) -> Result; + + fn cane_around_dot( + &mut self, + head: Head, + around: FixedDotIndex, + cw: bool, + width: f64, + ) -> Result; + + fn cane_around_bend( + &mut self, + head: Head, + around: BendIndex, + cw: bool, + width: f64, + ) -> Result; + + fn undo_cane(&mut self, head: CaneHead) -> Option; } -impl<'a, R: AccessRules> Draw<'a, R> { - pub fn new(layout: &'a mut Layout) -> Self { - Self { layout } - } - - pub fn start(&mut self, from: LooseDotIndex) -> Head { +impl<'a, R: AccessRules> Draw for RecordingLayout<'a, R> { + fn start(&mut self, from: LooseDotIndex) -> Head { self.guide().cane_head(from).into() } - #[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - pub fn finish_in_dot( + #[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))] + fn finish_in_dot( &mut self, - recorder: &mut LayoutEdit, head: Head, into: FixedDotIndex, width: f64, @@ -64,49 +84,43 @@ impl<'a, R: AccessRules> Draw<'a, R> { .guide() .head_into_dot_segment(&head, into, width) .map_err(Into::::into)?; - let head = self - .extend_head(recorder, head, tangent.start_point()) + let head = extend_head(self, head, tangent.start_point()) .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?; - let layer = head.face().primitive(self.layout.drawing()).layer(); - let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net(); + let layer = head.face().primitive(self.drawing()).layer(); + let maybe_net = head.face().primitive(self.drawing()).maybe_net(); Ok(match head.face() { DotIndex::Fixed(dot) => BandTermsegIndex::Straight( - self.layout - .recording(recorder) - .add_lone_loose_seg( - dot, - into, - LoneLooseSegWeight { - width, - layer, - maybe_net, - }, - ) - .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, + self.add_lone_loose_seg( + dot, + into, + LoneLooseSegWeight { + width, + layer, + maybe_net, + }, + ) + .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, ), DotIndex::Loose(dot) => BandTermsegIndex::Bended( - self.layout - .recording(recorder) - .add_seq_loose_seg( - into.into(), - dot, - SeqLooseSegWeight { - width, - layer, - maybe_net, - }, - ) - .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, + self.add_seq_loose_seg( + into.into(), + dot, + SeqLooseSegWeight { + width, + layer, + maybe_net, + }, + ) + .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, ), }) } - #[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))] - #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - pub fn cane_around_dot( + #[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))] + #[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))] + fn cane_around_dot( &mut self, - recorder: &mut LayoutEdit, head: Head, around: FixedDotIndex, cw: bool, @@ -118,8 +132,8 @@ impl<'a, R: AccessRules> Draw<'a, R> { let offset = self .guide() .head_around_dot_offset(&head, around.into(), width); - self.cane_around( - recorder, + cane_around( + self, head, around.into(), tangent.start_point(), @@ -131,11 +145,10 @@ impl<'a, R: AccessRules> Draw<'a, R> { .map_err(|err| DrawException::CannotWrapAround(around.into(), err)) } - #[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))] - #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - pub fn cane_around_bend( + #[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))] + #[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))] + fn cane_around_bend( &mut self, - recorder: &mut LayoutEdit, head: Head, around: BendIndex, cw: bool, @@ -146,8 +159,8 @@ impl<'a, R: AccessRules> Draw<'a, R> { .head_around_bend_segment(&head, around, cw, width)?; let offset = self.guide().head_around_bend_offset(&head, around, width); - self.cane_around( - recorder, + cane_around( + self, head, around.into(), tangent.start_point(), @@ -159,104 +172,88 @@ impl<'a, R: AccessRules> Draw<'a, R> { .map_err(|err| DrawException::CannotWrapAround(around.into(), err)) } - #[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))] - #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - fn cane_around( - &mut self, - recorder: &mut LayoutEdit, - head: Head, - around: GearIndex, - from: Point, - to: Point, - cw: bool, - width: f64, - offset: f64, - ) -> Result { - let head = self.extend_head(recorder, head, from)?; - self.cane(recorder, head, around, to, cw, width, offset) - } - - #[debug_ensures(self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - fn extend_head( - &mut self, - recorder: &mut LayoutEdit, - head: Head, - to: Point, - ) -> Result { - if let Head::Cane(head) = head { - self.layout - .recording(recorder) - .move_dot(head.face.into(), to)?; - Ok(Head::Cane(head)) - } else { - Ok(head) - } - } - - #[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))] - #[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - fn cane( - &mut self, - recorder: &mut LayoutEdit, - head: Head, - around: GearIndex, - to: Point, - cw: bool, - width: f64, - offset: f64, - ) -> Result { - let layer = head.face().primitive(self.layout.drawing()).layer(); - let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net(); - let cane = self.layout.recording(recorder).insert_cane( - head.face(), - around, - LooseDotWeight { - circle: Circle { - pos: to, - r: width / 2.0, - }, - layer, - maybe_net, - }, - SeqLooseSegWeight { - width, - layer, - maybe_net, - }, - LooseBendWeight { - width, - offset, - layer, - maybe_net, - }, - cw, - )?; - Ok(CaneHead { - face: self - .layout - .drawing() - .primitive(cane.bend) - .other_joint(cane.dot), - cane, - }) - } - - #[debug_ensures(ret.is_some() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() - 4))] - #[debug_ensures(ret.is_none() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))] - pub fn undo_cane(&mut self, recorder: &mut LayoutEdit, head: CaneHead) -> Option { + #[debug_ensures(ret.is_some() -> self.drawing().node_count() == old(self.drawing().node_count() - 4))] + #[debug_ensures(ret.is_none() -> self.drawing().node_count() == old(self.drawing().node_count()))] + fn undo_cane(&mut self, head: CaneHead) -> Option { let prev_dot = self - .layout .drawing() .primitive(head.cane.seg) .other_joint(head.cane.dot.into()); - self.layout - .recording(recorder) - .remove_cane(&head.cane, head.face); + self.remove_cane(&head.cane, head.face); Some(self.guide().head(prev_dot)) } +} - fn guide(&self) -> Guide { - Guide::new(self.layout.drawing()) +#[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))] +#[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))] +fn cane_around( + this: &mut RecordingLayout<'_, R>, + head: Head, + around: GearIndex, + from: Point, + to: Point, + cw: bool, + width: f64, + offset: f64, +) -> Result { + let head = extend_head(this, head, from)?; + cane(this, head, around, to, cw, width, offset) +} + +#[debug_ensures(this.drawing().node_count() == old(this.drawing().node_count()))] +fn extend_head( + this: &mut RecordingLayout<'_, R>, + head: Head, + to: Point, +) -> Result { + if let Head::Cane(head) = head { + this.move_dot(head.face.into(), to)?; + Ok(Head::Cane(head)) + } else { + Ok(head) } } + +#[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))] +#[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))] +fn cane( + this: &mut RecordingLayout<'_, R>, + head: Head, + around: GearIndex, + to: Point, + cw: bool, + width: f64, + offset: f64, +) -> Result { + let layer = head.face().primitive(this.drawing()).layer(); + let maybe_net = head.face().primitive(this.drawing()).maybe_net(); + let cane = this.insert_cane( + head.face(), + around, + LooseDotWeight { + circle: Circle { + pos: to, + r: width / 2.0, + }, + layer, + maybe_net, + }, + SeqLooseSegWeight { + width, + layer, + maybe_net, + }, + LooseBendWeight { + width, + offset, + layer, + maybe_net, + }, + cw, + )?; + Ok(CaneHead { + face: this.drawing().primitive(cane.bend).other_joint(cane.dot), + cane, + }) +} diff --git a/src/router/navcord.rs b/src/router/navcord.rs index 1363ced..ba5922c 100644 --- a/src/router/navcord.rs +++ b/src/router/navcord.rs @@ -85,13 +85,10 @@ impl NavcordStepper { cw: bool, width: f64, ) -> Result { - Ok(Draw::new(navcorder.layout).cane_around_dot( - &mut self.recorder, - head, - around, - cw, - width, - )?) + Ok(navcorder + .layout + .recording(&mut self.recorder) + .cane_around_dot(head, around, cw, width)?) } fn wrap_around_loose_bend( @@ -102,13 +99,10 @@ impl NavcordStepper { cw: bool, width: f64, ) -> Result { - Ok(Draw::new(navcorder.layout).cane_around_bend( - &mut self.recorder, - head, - around.into(), - cw, - width, - )?) + Ok(navcorder + .layout + .recording(&mut self.recorder) + .cane_around_bend(head, around.into(), cw, width)?) } fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex { @@ -159,8 +153,10 @@ impl NavcordStepper { navcorder: &mut Navcorder<'a, R>, ) -> Result<(), NavcorderException> { if let Head::Cane(head) = self.head { - self.head = Draw::new(navcorder.layout) - .undo_cane(&mut self.recorder, head) + self.head = navcorder + .layout + .recording(&mut self.recorder) + .undo_cane(head) .unwrap(); } else { panic!(); diff --git a/src/router/navcorder.rs b/src/router/navcorder.rs index a950854..96c50bf 100644 --- a/src/router/navcorder.rs +++ b/src/router/navcorder.rs @@ -53,8 +53,7 @@ impl<'a, R: AccessRules> Navcorder<'a, R> { target: FixedDotIndex, width: f64, ) -> Result { - Ok(Draw::new(self.layout).finish_in_dot( - &mut navcord.recorder, + Ok(self.layout.recording(&mut navcord.recorder).finish_in_dot( navcord.head, target, width,