diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 20c53d7..406e696 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -86,7 +86,8 @@ impl Autorouter { pub fn undo_pointroute(&mut self, band: BandTermsegIndex) -> Result<(), AutorouterError> { self.board .layout_mut() - .remove_band(&mut LayoutEdit::new(), band) + .recording(&mut LayoutEdit::new()) + .remove_band(band) .map_err(|_| AutorouterError::CouldNotRemoveBand(band)) } @@ -124,7 +125,8 @@ impl Autorouter { .unwrap(); self.board .layout_mut() - .remove_band(&mut LayoutEdit::new(), band) + .recording(&mut LayoutEdit::new()) + .remove_band(band) .map_err(|_| AutorouterError::CouldNotRemoveBand(band))?; } diff --git a/src/autorouter/place_via.rs b/src/autorouter/place_via.rs index 67c9c76..361f76c 100644 --- a/src/autorouter/place_via.rs +++ b/src/autorouter/place_via.rs @@ -44,7 +44,8 @@ impl PlaceViaExecutionStepper { autorouter .board .layout_mut() - .add_via(&mut edit, self.weight)?; + .recording(&mut edit) + .add_via(self.weight)?; Ok(Some(edit)) } else { Ok(None) diff --git a/src/autorouter/remove_bands.rs b/src/autorouter/remove_bands.rs index 8f73279..0cbcea6 100644 --- a/src/autorouter/remove_bands.rs +++ b/src/autorouter/remove_bands.rs @@ -42,7 +42,11 @@ impl RemoveBandsExecutionStepper { let mut edit = LayoutEdit::new(); for selector in self.selection.selectors() { let band = autorouter.board.bandname_band(&selector.band).unwrap().0; - autorouter.board.layout_mut().remove_band(&mut edit, band); + autorouter + .board + .layout_mut() + .recording(&mut edit) + .remove_band(band); } Ok(Some(edit)) } else { diff --git a/src/board/mod.rs b/src/board/mod.rs index 8916e59..6daa3be 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -91,7 +91,10 @@ impl Board { weight: FixedDotWeight, maybe_pin: Option, ) -> FixedDotIndex { - let dot = self.layout.add_fixed_dot_infringably(recorder, weight); + let dot = self + .layout + .recording(recorder) + .add_fixed_dot_infringably(weight); if let Some(pin) = maybe_pin { self.node_to_pinname @@ -112,7 +115,8 @@ impl Board { ) -> FixedDotIndex { let dot = self .layout - .add_poly_fixed_dot_infringably(recorder, weight, poly); + .recording(recorder) + .add_poly_fixed_dot_infringably(weight, poly); if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { self.node_to_pinname @@ -135,7 +139,8 @@ impl Board { ) -> FixedSegIndex { let seg = self .layout - .add_fixed_seg_infringably(recorder, from, to, weight); + .recording(recorder) + .add_fixed_seg_infringably(from, to, weight); if let Some(pin) = maybe_pin { self.node_to_pinname @@ -158,7 +163,8 @@ impl Board { ) -> FixedSegIndex { let seg = self .layout - .add_poly_fixed_seg_infringably(recorder, from, to, weight, poly); + .recording(recorder) + .add_poly_fixed_seg_infringably(from, to, weight, poly); if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { self.node_to_pinname @@ -177,7 +183,7 @@ impl Board { weight: PolyWeight, maybe_pin: Option, ) -> GenericIndex { - let poly = self.layout.add_poly(recorder, weight); + let poly = self.layout.recording(recorder).add_poly(weight); if let Some(pin) = maybe_pin { self.node_to_pinname diff --git a/src/layout/layout.rs b/src/layout/layout.rs index e5a1b24..d26fdd9 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -22,7 +22,7 @@ use crate::{ FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, SegWeight, SeqLooseSegIndex, SeqLooseSegWeight, }, - Drawing, DrawingEdit, DrawingException, Infringement, + Drawing, DrawingEdit, DrawingException, Infringement, RecordingDrawing, }, geometry::{edit::ApplyGeometryEdit, shape::Shape, GenericNode}, graph::{GenericIndex, GetPetgraphIndex}, @@ -52,245 +52,27 @@ pub struct Layout { drawing: Drawing, } +pub struct RecordingLayout<'a, R> { + pub layout: &'a mut Layout, + pub recorder: &'a mut LayoutEdit, +} + impl Layout { + #[inline(always)] pub fn new(drawing: Drawing) -> Self { Self { drawing } } + + #[inline(always)] + pub fn recording<'a>(&'a mut self, recorder: &'a mut LayoutEdit) -> RecordingLayout<'a, R> { + RecordingLayout { + layout: self, + recorder, + } + } } impl Layout { - /// Insert [`Cane`] object into the [`Layout`] - pub fn insert_cane( - &mut self, - recorder: &mut LayoutEdit, - from: DotIndex, - around: GearIndex, - dot_weight: LooseDotWeight, - seg_weight: SeqLooseSegWeight, - bend_weight: LooseBendWeight, - cw: bool, - ) -> Result { - self.drawing.recording(recorder).insert_cane( - from, - around, - dot_weight, - seg_weight, - bend_weight, - cw, - ) - } - - /// Remove [`Cane`] object from the [`Layout`] - pub fn remove_cane(&mut self, recorder: &mut LayoutEdit, cane: &Cane, face: LooseDotIndex) { - self.drawing.recording(recorder).remove_cane(cane, face) - } - - #[debug_ensures(ret.is_ok() -> self.drawing.node_count() == old(self.drawing.node_count()) + weight.to_layer - weight.from_layer + 2)] - #[debug_ensures(ret.is_err() -> self.drawing.node_count() == old(self.drawing.node_count()))] - /// Insert [`Via`] into the [`Layout`] - pub fn add_via( - &mut self, - recorder: &mut LayoutEdit, - weight: ViaWeight, - ) -> Result, Infringement> { - let compound = self.drawing.recording(recorder).add_compound(weight.into()); - let mut dots = vec![]; - - for layer in weight.from_layer..=weight.to_layer { - match self - .drawing - .recording(recorder) - .add_fixed_dot(FixedDotWeight { - circle: weight.circle, - layer, - maybe_net: weight.maybe_net, - }) { - Ok(dot) => { - self.drawing - .recording(recorder) - .add_to_compound(dot, compound); - dots.push(dot); - } - Err(err) => { - // Remove inserted dots. - - self.drawing.recording(recorder).remove_compound(compound); - - for dot in dots.iter().rev() { - self.drawing.recording(recorder).remove_fixed_dot(*dot); - } - - return Err(err); - } - } - } - - Ok(GenericIndex::::new(compound.petgraph_index())) - } - - pub fn add_fixed_dot( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - ) -> Result { - self.drawing.recording(recorder).add_fixed_dot(weight) - } - - pub fn add_fixed_dot_infringably( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - ) -> FixedDotIndex { - self.drawing - .recording(recorder) - .add_fixed_dot_infringably(weight) - } - - pub fn add_poly_fixed_dot( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - poly: GenericIndex, - ) -> Result { - let maybe_dot = self.drawing.recording(recorder).add_fixed_dot(weight); - - if let Ok(dot) = maybe_dot { - self.drawing - .recording(recorder) - .add_to_compound(dot, poly.into()); - } - - maybe_dot - } - - pub fn add_poly_fixed_dot_infringably( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - poly: GenericIndex, - ) -> FixedDotIndex { - let dot = self - .drawing - .recording(recorder) - .add_fixed_dot_infringably(weight); - self.drawing - .recording(recorder) - .add_to_compound(dot, poly.into()); - dot - } - - pub fn add_fixed_seg( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - ) -> Result { - self.drawing - .recording(recorder) - .add_fixed_seg(from, to, weight) - } - - pub fn add_fixed_seg_infringably( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - ) -> FixedSegIndex { - self.drawing - .recording(recorder) - .add_fixed_seg_infringably(from, to, weight) - } - - pub fn add_poly_fixed_seg( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - poly: GenericIndex, - ) -> Result { - let maybe_seg = self.add_fixed_seg(recorder, from, to, weight); - - if let Ok(seg) = maybe_seg { - self.drawing - .recording(recorder) - .add_to_compound(seg, poly.into()); - } - - maybe_seg - } - - pub fn add_poly_fixed_seg_infringably( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - poly: GenericIndex, - ) -> FixedSegIndex { - let seg = self.add_fixed_seg_infringably(recorder, from, to, weight); - self.drawing - .recording(recorder) - .add_to_compound(seg, poly.into()); - seg - } - - pub fn add_lone_loose_seg( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: LoneLooseSegWeight, - ) -> Result { - self.drawing - .recording(recorder) - .add_lone_loose_seg(from, to, weight) - } - - pub fn add_seq_loose_seg( - &mut self, - recorder: &mut LayoutEdit, - from: DotIndex, - to: LooseDotIndex, - weight: SeqLooseSegWeight, - ) -> Result { - self.drawing - .recording(recorder) - .add_seq_loose_seg(from, to, weight) - } - - pub fn move_dot( - &mut self, - recorder: &mut LayoutEdit, - dot: DotIndex, - to: Point, - ) -> Result<(), Infringement> { - self.drawing.recording(recorder).move_dot(dot, to) - } - - pub fn add_poly( - &mut self, - recorder: &mut LayoutEdit, - weight: PolyWeight, - ) -> GenericIndex { - GenericIndex::::new( - self.drawing - .recording(recorder) - .add_compound(CompoundWeight::Poly(weight)) - .petgraph_index(), - ) - } - - pub fn remove_band( - &mut self, - recorder: &mut LayoutEdit, - band: BandTermsegIndex, - ) -> Result<(), DrawingException> { - self.drawing.recording(recorder).remove_band(band) - } - pub fn polys( &self, node: GenericIndex, @@ -418,6 +200,179 @@ impl Layout { } } +impl RecordingLayout<'_, R> { + fn recording_drawing(&mut self) -> RecordingDrawing<'_, CompoundWeight, R> { + self.layout.drawing.recording(self.recorder) + } + + /// Insert [`Cane`] object into the [`Layout`] + pub fn insert_cane( + &mut self, + from: DotIndex, + around: GearIndex, + dot_weight: LooseDotWeight, + seg_weight: SeqLooseSegWeight, + bend_weight: LooseBendWeight, + cw: bool, + ) -> Result { + self.recording_drawing() + .insert_cane(from, around, dot_weight, seg_weight, bend_weight, cw) + } + + /// Remove [`Cane`] object from the [`Layout`] + pub fn remove_cane(&mut self, cane: &Cane, face: LooseDotIndex) { + self.recording_drawing().remove_cane(cane, face) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.node_count() == old(self.drawing.node_count()) + weight.to_layer - weight.from_layer + 2)] + #[debug_ensures(ret.is_err() -> self.drawing.node_count() == old(self.drawing.node_count()))] + /// Insert [`Via`] into the [`Layout`] + pub fn add_via(&mut self, weight: ViaWeight) -> Result, Infringement> { + let compound = self.recording_drawing().add_compound(weight.into()); + let mut dots = vec![]; + + for layer in weight.from_layer..=weight.to_layer { + match self.recording_drawing().add_fixed_dot(FixedDotWeight { + circle: weight.circle, + layer, + maybe_net: weight.maybe_net, + }) { + Ok(dot) => { + self.recording_drawing().add_to_compound(dot, compound); + dots.push(dot); + } + Err(err) => { + // Remove inserted dots. + + self.recording_drawing().remove_compound(compound); + + for dot in dots.iter().rev() { + self.recording_drawing().remove_fixed_dot(*dot); + } + + return Err(err); + } + } + } + + Ok(GenericIndex::::new(compound.petgraph_index())) + } + + pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result { + self.recording_drawing().add_fixed_dot(weight) + } + + pub fn add_fixed_dot_infringably(&mut self, weight: FixedDotWeight) -> FixedDotIndex { + self.recording_drawing().add_fixed_dot_infringably(weight) + } + + pub fn add_poly_fixed_dot( + &mut self, + weight: FixedDotWeight, + poly: GenericIndex, + ) -> Result { + let maybe_dot = self.recording_drawing().add_fixed_dot(weight); + + if let Ok(dot) = maybe_dot { + self.recording_drawing().add_to_compound(dot, poly.into()); + } + + maybe_dot + } + + pub fn add_poly_fixed_dot_infringably( + &mut self, + weight: FixedDotWeight, + poly: GenericIndex, + ) -> FixedDotIndex { + let dot = self.recording_drawing().add_fixed_dot_infringably(weight); + self.recording_drawing().add_to_compound(dot, poly.into()); + dot + } + + pub fn add_fixed_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + ) -> Result { + self.recording_drawing().add_fixed_seg(from, to, weight) + } + + pub fn add_fixed_seg_infringably( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + ) -> FixedSegIndex { + self.recording_drawing() + .add_fixed_seg_infringably(from, to, weight) + } + + pub fn add_poly_fixed_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + poly: GenericIndex, + ) -> Result { + let maybe_seg = self.add_fixed_seg(from, to, weight); + + if let Ok(seg) = maybe_seg { + self.recording_drawing().add_to_compound(seg, poly.into()); + } + + maybe_seg + } + + pub fn add_poly_fixed_seg_infringably( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + poly: GenericIndex, + ) -> FixedSegIndex { + let seg = self.add_fixed_seg_infringably(from, to, weight); + self.recording_drawing().add_to_compound(seg, poly.into()); + seg + } + + pub fn add_lone_loose_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: LoneLooseSegWeight, + ) -> Result { + self.recording_drawing() + .add_lone_loose_seg(from, to, weight) + } + + pub fn add_seq_loose_seg( + &mut self, + from: DotIndex, + to: LooseDotIndex, + weight: SeqLooseSegWeight, + ) -> Result { + self.recording_drawing().add_seq_loose_seg(from, to, weight) + } + + pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { + self.recording_drawing().move_dot(dot, to) + } + + pub fn add_poly(&mut self, weight: PolyWeight) -> GenericIndex { + GenericIndex::::new( + self.recording_drawing() + .add_compound(CompoundWeight::Poly(weight)) + .petgraph_index(), + ) + } + + pub fn remove_band(&mut self, band: BandTermsegIndex) -> Result<(), DrawingException> { + self.recording_drawing().remove_band(band) + } +} + impl ApplyGeometryEdit< PrimitiveWeight, diff --git a/src/router/draw.rs b/src/router/draw.rs index 9d0b540..0329847 100644 --- a/src/router/draw.rs +++ b/src/router/draw.rs @@ -73,8 +73,8 @@ impl<'a, R: AccessRules> Draw<'a, R> { Ok(match head.face() { DotIndex::Fixed(dot) => BandTermsegIndex::Straight( self.layout + .recording(recorder) .add_lone_loose_seg( - recorder, dot, into, LoneLooseSegWeight { @@ -87,8 +87,8 @@ impl<'a, R: AccessRules> Draw<'a, R> { ), DotIndex::Loose(dot) => BandTermsegIndex::Bended( self.layout + .recording(recorder) .add_seq_loose_seg( - recorder, into.into(), dot, SeqLooseSegWeight { @@ -184,7 +184,9 @@ 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.layout + .recording(recorder) + .move_dot(head.face.into(), to)?; Ok(Head::Cane(head)) } else { Ok(head) @@ -205,8 +207,7 @@ impl<'a, R: AccessRules> Draw<'a, R> { ) -> 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( - recorder, + let cane = self.layout.recording(recorder).insert_cane( head.face(), around, LooseDotWeight { @@ -249,7 +250,9 @@ impl<'a, R: AccessRules> Draw<'a, R> { .primitive(head.cane.seg) .other_joint(head.cane.dot.into()); - self.layout.remove_cane(recorder, &head.cane, head.face); + self.layout + .recording(recorder) + .remove_cane(&head.cane, head.face); Some(self.guide().head(prev_dot)) }