From 1d110111330dfbd7a0d72dcc2b78a70d69d491a3 Mon Sep 17 00:00:00 2001 From: Ellen Emilia Anna Zscheile Date: Sat, 1 Feb 2025 23:22:40 +0100 Subject: [PATCH] refactor(router::draw): turn Draw into a trait --- src/router/draw.rs | 208 +++++++++++++++++++++++++--------------- src/router/navcord.rs | 23 ++--- src/router/navcorder.rs | 9 +- 3 files changed, 143 insertions(+), 97 deletions(-) diff --git a/src/router/draw.rs b/src/router/draw.rs index 9d0b540..53431fc 100644 --- a/src/router/draw.rs +++ b/src/router/draw.rs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2024 Topola contributors // // SPDX-License-Identifier: MIT +//! router module's routines for drawing and erasing the primitives +//! to pull out or contract the currently routed band. use contracts_try::debug_ensures; use geo::Point; @@ -20,7 +22,7 @@ use crate::{ seg::{LoneLooseSegWeight, SeqLooseSegWeight}, DrawingException, Infringement, }, - layout::{Layout, LayoutEdit}, + layout::{CompoundWeight, Layout, LayoutEdit}, math::{Circle, NoTangents}, }; @@ -35,25 +37,46 @@ pub enum DrawException { 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> { - layout: &'a mut Layout, +pub trait Draw { + fn start(&mut self, from: LooseDotIndex) -> Head; + + fn finish_in_dot( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + into: FixedDotIndex, + width: f64, + ) -> Result; + + fn cane_around_dot( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + around: FixedDotIndex, + cw: bool, + width: f64, + ) -> Result; + + fn cane_around_bend( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + around: BendIndex, + cw: bool, + width: f64, + ) -> Result; + + fn undo_cane(&mut self, recorder: &mut LayoutEdit, 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 Draw for Layout { + 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, @@ -67,44 +90,42 @@ impl<'a, R: AccessRules> Draw<'a, R> { let head = self .extend_head(recorder, 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 - .add_lone_loose_seg( - recorder, - dot, - into, - LoneLooseSegWeight { - width, - layer, - maybe_net, - }, - ) - .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, + self.add_lone_loose_seg( + recorder, + dot, + into, + LoneLooseSegWeight { + width, + layer, + maybe_net, + }, + ) + .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, ), DotIndex::Loose(dot) => BandTermsegIndex::Bended( - self.layout - .add_seq_loose_seg( - recorder, - into.into(), - dot, - SeqLooseSegWeight { - width, - layer, - maybe_net, - }, - ) - .map_err(|err| DrawException::CannotFinishIn(into, err.into()))?, + self.add_seq_loose_seg( + recorder, + 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, @@ -131,9 +152,9 @@ 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, @@ -159,8 +180,60 @@ 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()))] + #[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, recorder: &mut LayoutEdit, head: CaneHead) -> Option { + let prev_dot = self + .drawing() + .primitive(head.cane.seg) + .other_joint(head.cane.dot.into()); + + self.remove_cane(recorder, &head.cane, head.face); + Some(self.guide().head(prev_dot)) + } +} + +trait DrawPrivate { + type R; + + fn cane_around( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + around: GearIndex, + from: Point, + to: Point, + cw: bool, + width: f64, + offset: f64, + ) -> Result; + + fn extend_head( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + to: Point, + ) -> Result; + + fn cane( + &mut self, + recorder: &mut LayoutEdit, + head: Head, + around: GearIndex, + to: Point, + cw: bool, + width: f64, + offset: f64, + ) -> Result; + + fn guide(&self) -> Guide; +} + +impl DrawPrivate for Layout { + type R = R; + + #[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( &mut self, recorder: &mut LayoutEdit, @@ -176,7 +249,7 @@ impl<'a, R: AccessRules> Draw<'a, R> { 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.drawing().node_count() == old(self.drawing().node_count()))] fn extend_head( &mut self, recorder: &mut LayoutEdit, @@ -184,15 +257,15 @@ impl<'a, R: AccessRules> Draw<'a, R> { to: Point, ) -> Result { if let Head::Cane(head) = head { - self.layout.move_dot(recorder, head.face.into(), to)?; + self.move_dot(recorder, 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()))] + #[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( &mut self, recorder: &mut LayoutEdit, @@ -203,9 +276,9 @@ impl<'a, R: AccessRules> Draw<'a, R> { 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.insert_cane( + let layer = head.face().primitive(self.drawing()).layer(); + let maybe_net = head.face().primitive(self.drawing()).maybe_net(); + let cane = self.insert_cane( recorder, head.face(), around, @@ -231,29 +304,12 @@ impl<'a, R: AccessRules> Draw<'a, R> { cw, )?; Ok(CaneHead { - face: self - .layout - .drawing() - .primitive(cane.bend) - .other_joint(cane.dot), + face: self.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 { - let prev_dot = self - .layout - .drawing() - .primitive(head.cane.seg) - .other_joint(head.cane.dot.into()); - - self.layout.remove_cane(recorder, &head.cane, head.face); - Some(self.guide().head(prev_dot)) - } - - fn guide(&self) -> Guide { - Guide::new(self.layout.drawing()) + fn guide(&self) -> Guide { + Guide::new(self.drawing()) } } diff --git a/src/router/navcord.rs b/src/router/navcord.rs index 1363ced..cbba962 100644 --- a/src/router/navcord.rs +++ b/src/router/navcord.rs @@ -85,13 +85,9 @@ 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 + .cane_around_dot(&mut self.recorder, head, around, cw, width)?) } fn wrap_around_loose_bend( @@ -102,13 +98,9 @@ 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 + .cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?) } fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex { @@ -159,7 +151,8 @@ impl NavcordStepper { navcorder: &mut Navcorder<'a, R>, ) -> Result<(), NavcorderException> { if let Head::Cane(head) = self.head { - self.head = Draw::new(navcorder.layout) + self.head = navcorder + .layout .undo_cane(&mut self.recorder, head) .unwrap(); } else { diff --git a/src/router/navcorder.rs b/src/router/navcorder.rs index a950854..29c61ea 100644 --- a/src/router/navcorder.rs +++ b/src/router/navcorder.rs @@ -53,12 +53,9 @@ impl<'a, R: AccessRules> Navcorder<'a, R> { target: FixedDotIndex, width: f64, ) -> Result { - Ok(Draw::new(self.layout).finish_in_dot( - &mut navcord.recorder, - navcord.head, - target, - width, - )?) + Ok(self + .layout + .finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?) } #[debug_requires(path[0] == navcord.path[0])]