From 3b47c4a30eedccdb55183f801a95b32861328b46 Mon Sep 17 00:00:00 2001 From: Alain Emilia Anna Zscheile Date: Fri, 3 Jan 2025 03:15:43 +0100 Subject: [PATCH] refactor(drawing,geometry): separate RecordingDrawing, RecordingWithRtree as mutable borrowing wrappers --- src/drawing/drawing.rs | 1565 +++++++++++++------------- src/geometry/recording_with_rtree.rs | 188 +--- src/geometry/with_rtree.rs | 95 ++ src/layout/layout.rs | 76 +- 4 files changed, 945 insertions(+), 979 deletions(-) diff --git a/src/drawing/drawing.rs b/src/drawing/drawing.rs index 45abfee..a7124da 100644 --- a/src/drawing/drawing.rs +++ b/src/drawing/drawing.rs @@ -11,10 +11,12 @@ use rstar::{RTree, AABB}; use thiserror::Error; use crate::geometry::{ + compound::ManageCompounds, edit::{ApplyGeometryEdit, GeometryEdit}, primitive::{AccessPrimitiveShape, PrimitiveShape}, recording_with_rtree::RecordingGeometryWithRtree, with_rtree::BboxedIndex, + with_rtree::GeometryWithRtree, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, GetOffset, GetPos, GetWidth, }; @@ -84,7 +86,7 @@ pub type DrawingEdit = GeometryEdit< #[derive(Debug, Getters)] pub struct Drawing { - recording_geometry_with_rtree: RecordingGeometryWithRtree< + geometry_with_rtree: GeometryWithRtree< PrimitiveWeight, DotWeight, SegWeight, @@ -98,738 +100,50 @@ pub struct Drawing { rules: R, } +pub struct RecordingDrawing<'a, CW, R> { + pub drawing: &'a mut Drawing, + pub recorder: &'a mut DrawingEdit, +} + #[debug_invariant(self.test_if_looses_dont_infringe_each_other())] impl Drawing { pub fn new(rules: R, layer_count: usize) -> Self { Self { - recording_geometry_with_rtree: RecordingGeometryWithRtree::new(layer_count), + geometry_with_rtree: GeometryWithRtree::new(layer_count), rules, } } - pub fn remove_band( - &mut self, - recorder: &mut DrawingEdit, - band: BandTermsegIndex, - ) -> Result<(), DrawingException> { - match band { - BandTermsegIndex::Straight(seg) => { - self.recording_geometry_with_rtree - .remove_seg(recorder, seg.into()); - } - BandTermsegIndex::Bended(first_loose_seg) => { - let mut dots = vec![]; - let mut segs = vec![]; - let mut bends = vec![]; - let mut outers = vec![]; - - let mut maybe_loose = Some(first_loose_seg.into()); - let mut prev = None; - - while let Some(loose) = maybe_loose { - match loose { - LooseIndex::Dot(dot) => { - dots.push(dot); - } - LooseIndex::LoneSeg(seg) => { - self.recording_geometry_with_rtree - .remove_seg(recorder, seg.into()); - break; - } - LooseIndex::SeqSeg(seg) => { - segs.push(seg); - } - LooseIndex::Bend(bend) => { - bends.push(bend); - - if let Some(outer) = self.primitive(bend).outer() { - outers.push(outer); - self.reattach_bend(recorder, outer, self.primitive(bend).inner()); - } - } - } - - let prev_prev = prev; - prev = maybe_loose; - maybe_loose = self.loose(loose).next_loose(prev_prev); - } - - for bend in bends { - self.recording_geometry_with_rtree - .remove_bend(recorder, bend.into()); - } - - for seg in segs { - self.recording_geometry_with_rtree - .remove_seg(recorder, seg.into()); - } - - // We must remove the dots only after the segs and bends because we need dots to calculate - // the shapes, which we first need unchanged to remove the segs and bends from the R-tree. - - for dot in dots { - self.recording_geometry_with_rtree - .remove_dot(recorder, dot.into()); - } - - for outer in outers { - self.update_this_and_outward_bows(recorder, outer)?; - } - } - } - - Ok(()) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_fixed_dot( - &mut self, - recorder: &mut DrawingEdit, - weight: FixedDotWeight, - ) -> Result { - self.add_dot_with_infringables(recorder, weight, Some(&[])) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() - 1))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn remove_fixed_dot(&mut self, recorder: &mut DrawingEdit, dot: FixedDotIndex) { - self.recording_geometry_with_rtree - .remove_dot(recorder, dot.into()); - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_fixed_dot_infringably( - &mut self, - recorder: &mut DrawingEdit, - weight: FixedDotWeight, - ) -> FixedDotIndex { - self.add_dot_infringably(recorder, weight) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - fn add_dot_with_infringables + GetLayer>( - &mut self, - recorder: &mut DrawingEdit, - weight: W, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result, Infringement> - where - GenericIndex: Into + Copy, - { - let dot = self.add_dot_infringably(recorder, weight); - self.fail_and_remove_if_infringes_except(recorder, dot.into(), infringables)?; - - Ok(dot) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_fixed_seg( - &mut self, - recorder: &mut DrawingEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - ) -> Result { - self.add_seg_with_infringables(recorder, from.into(), to.into(), weight, Some(&[])) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 2))] - pub fn add_fixed_seg_infringably( - &mut self, - recorder: &mut DrawingEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - ) -> FixedSegIndex { - self.add_seg_infringably(recorder, from.into(), to.into(), weight) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 2))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_lone_loose_seg( - &mut self, - recorder: &mut DrawingEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: LoneLooseSegWeight, - ) -> Result { - let seg = - self.add_seg_with_infringables(recorder, from.into(), to.into(), weight, Some(&[]))?; - Ok(seg) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 2))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_seq_loose_seg( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - to: LooseDotIndex, - weight: SeqLooseSegWeight, - ) -> Result { - let seg = self.add_seg_with_infringables(recorder, from, to.into(), weight, Some(&[]))?; - Ok(seg) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() >= old(self.recording_geometry_with_rtree.graph().edge_count() + 2))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_seg_with_infringables + GetLayer>( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - to: DotIndex, - weight: W, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result, Infringement> - where - GenericIndex: Into + Copy, - { - let seg = self.add_seg_infringably(recorder, from, to, weight); - self.fail_and_remove_if_infringes_except(recorder, seg.into(), infringables)?; - - Ok(seg) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 3) - || self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 4))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_loose_bend_with_infringables( - &mut self, - recorder: &mut DrawingEdit, - from: LooseDotIndex, - to: LooseDotIndex, - around: GearIndex, - weight: LooseBendWeight, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result { - // It makes no sense to wrap something around or under one of its connectables. - // - if let Some(net) = weight.maybe_net { - if let Some(around_net) = around.primitive(self).maybe_net() { - if net == around_net { - return Err(AlreadyConnected(net, around.into()).into()); - } - } - // - if let Some(next_gear) = around.ref_(self).next_gear() { - if let Some(next_gear_net) = next_gear.primitive(self).maybe_net() { - if net == next_gear_net { - return Err(AlreadyConnected(net, next_gear.into()).into()); - } - } - } - } - - match around { - GearIndex::FixedDot(core) => self - .add_core_bend_with_infringables( - recorder, - from.into(), - to.into(), - core, - weight, - infringables, - ) - .map_err(Into::into), - GearIndex::FixedBend(around) => self - .add_outer_bend_with_infringables( - recorder, - from, - to, - around.into(), - weight, - infringables, - ) - .map_err(Into::into), - GearIndex::LooseBend(around) => self - .add_outer_bend_with_infringables( - recorder, - from, - to, - around.into(), - weight, - infringables, - ) - .map_err(Into::into), - } - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 3))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_core_bend_with_infringables + GetLayer>( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - to: DotIndex, - core: FixedDotIndex, - weight: W, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result, Infringement> - where - GenericIndex: Into + Copy, - { - let bend = - self.recording_geometry_with_rtree - .add_bend(recorder, from, to, core.into(), weight); - - self.fail_and_remove_if_infringes_except(recorder, bend.into(), infringables)?; - Ok(bend) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 4))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_outer_bend_with_infringables( - &mut self, - recorder: &mut DrawingEdit, - from: LooseDotIndex, - to: LooseDotIndex, - inner: BendIndex, - weight: LooseBendWeight, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result, Infringement> { - let core = *self - .recording_geometry_with_rtree - .graph() - .neighbors(inner.petgraph_index()) - .filter(|ni| { - matches!( - self.recording_geometry_with_rtree - .graph() - .edge_weight( - self.recording_geometry_with_rtree - .graph() - .find_edge(inner.petgraph_index(), *ni) - .unwrap() - ) - .unwrap(), - GeometryLabel::Core - ) - }) - .map(FixedDotIndex::new) - .collect::>() - .first() - .unwrap(); - - let bend = self.recording_geometry_with_rtree.add_bend( + #[inline(always)] + pub fn recording<'a>( + &'a mut self, + recorder: &'a mut DrawingEdit, + ) -> RecordingDrawing<'a, CW, R> { + RecordingDrawing { + drawing: self, recorder, - from.into(), - to.into(), - core.into(), - weight, - ); - self.recording_geometry_with_rtree - .reattach_bend(recorder, bend.into(), Some(inner)); - - self.fail_and_remove_if_infringes_except(recorder, bend.into(), infringables)?; - Ok(bend) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn flip_bend(&mut self, recorder: &mut DrawingEdit, bend: FixedBendIndex) { - self.recording_geometry_with_rtree - .flip_bend(recorder, bend.into()); - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()) - || self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() - 1) - || self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 1))] - fn reattach_bend( - &mut self, - recorder: &mut DrawingEdit, - bend: LooseBendIndex, - maybe_new_inner: Option, - ) { - self.recording_geometry_with_rtree.reattach_bend( - recorder, - bend.into(), - maybe_new_inner.map(Into::into), - ); - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 4))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() >= old(self.recording_geometry_with_rtree.graph().edge_count() + 5))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn insert_cane( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - around: GearIndex, - dot_weight: LooseDotWeight, - seg_weight: SeqLooseSegWeight, - bend_weight: LooseBendWeight, - cw: bool, - ) -> Result { - let maybe_next_gear = around.ref_(self).next_gear(); - let cane = self.add_cane_with_infringables( - recorder, - from, - around, - dot_weight, - seg_weight, - bend_weight, - cw, - Some(&[]), - )?; - - if let Some(next_gear) = maybe_next_gear { - self.reattach_bend(recorder, next_gear, Some(cane.bend)); - } - - if let Some(outer) = self.primitive(cane.bend).outer() { - self.update_this_and_outward_bows(recorder, outer) - .inspect_err(|_| { - let joint = self.primitive(cane.bend).other_joint(cane.dot); - self.remove_cane(recorder, &cane, joint); - })?; - } - - // Segs must not cross. - if let Some(collision) = self.detect_collision(cane.seg.into()) { - let joint = self.primitive(cane.bend).other_joint(cane.dot); - self.remove_cane(recorder, &cane, joint); - Err(collision.into()) - } else { - Ok(cane) } } - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn update_this_and_outward_bows( - &mut self, - recorder: &mut DrawingEdit, - around: LooseBendIndex, - ) -> Result<(), DrawingException> { - // FIXME: Fail gracefully on infringement. - let mut maybe_rail = Some(around); - - while let Some(rail) = maybe_rail { - let rail_primitive = self.primitive(rail); - let joints = rail_primitive.joints(); - - let guide = Guide::new(self); - let from_head = guide.rear_head(joints.1); - let to_head = guide.rear_head(joints.0); - - if let Some(inner) = rail_primitive.inner() { - let from = guide - .head_around_bend_segment( - &from_head, - inner.into(), - true, - self.primitive(rail).width(), - )? - .end_point(); - let to = guide - .head_around_bend_segment( - &to_head, - inner.into(), - false, - self.primitive(rail).width(), - )? - .end_point(); - let offset = guide.head_around_bend_offset( - &from_head, - inner.into(), - self.primitive(rail).width(), - ); - - self.move_dot_with_infringables( - recorder, - joints.0.into(), - from, - Some(&self.collect().bend_outer_bows(rail)), - )?; - self.move_dot_with_infringables( - recorder, - joints.1.into(), - to, - Some(&self.collect().bend_outer_bows(rail)), - )?; - - self.shift_bend_with_infringables( - recorder, - rail.into(), - offset, - Some(&self.collect().bend_outer_bows(rail)), - )?; - - // Update offsets in case the rule conditions changed. - } else { - let core = rail_primitive.core(); - let from = guide - .head_around_dot_segment( - &from_head, - core.into(), - true, - self.primitive(rail).width(), - )? - .end_point(); - let to = guide - .head_around_dot_segment( - &to_head, - core.into(), - false, - self.primitive(rail).width(), - )? - .end_point(); - let offset = guide.head_around_dot_offset( - &from_head, - core.into(), - self.primitive(rail).width(), - ); - - self.move_dot_with_infringables( - recorder, - joints.0.into(), - from, - Some(&self.collect().bend_outer_bows(rail)), - )?; - self.move_dot_with_infringables( - recorder, - joints.1.into(), - to, - Some(&self.collect().bend_outer_bows(rail)), - )?; - - self.shift_bend_with_infringables( - recorder, - rail.into(), - offset, - Some(&self.collect().bend_outer_bows(rail)), - )?; - } - - maybe_rail = self.primitive(rail).outer(); - } - - Ok(()) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 4))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() >= old(self.recording_geometry_with_rtree.graph().edge_count() + 5))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn add_cane( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - around: GearIndex, - dot_weight: LooseDotWeight, - seg_weight: SeqLooseSegWeight, - bend_weight: LooseBendWeight, - cw: bool, - ) -> Result { - self.add_cane_with_infringables( - recorder, - from, - around, - dot_weight, - seg_weight, - bend_weight, - cw, - Some(&[]), - ) - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 4))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() >= old(self.recording_geometry_with_rtree.graph().edge_count() + 5))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_cane_with_infringables( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - around: GearIndex, - dot_weight: LooseDotWeight, - seg_weight: SeqLooseSegWeight, - bend_weight: LooseBendWeight, - cw: bool, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result { - let seg_to = self.add_dot_with_infringables(recorder, dot_weight, infringables)?; - let seg = self - .add_seg_with_infringables(recorder, from, seg_to.into(), seg_weight, infringables) - .inspect_err(|_| { - self.recording_geometry_with_rtree - .remove_dot(recorder, seg_to.into()); - })?; - - let to = self - .add_dot_with_infringables(recorder, dot_weight, infringables) - .inspect_err(|_| { - self.recording_geometry_with_rtree - .remove_seg(recorder, seg.into()); - self.recording_geometry_with_rtree - .remove_dot(recorder, seg_to.into()); - })?; - - let (bend_from, bend_to) = if cw { (to, seg_to) } else { (seg_to, to) }; - - let bend = self - .add_loose_bend_with_infringables( - recorder, - bend_from, - bend_to, - around, - bend_weight, - infringables, - ) - .inspect_err(|_| { - self.recording_geometry_with_rtree - .remove_dot(recorder, to.into()); - self.recording_geometry_with_rtree - .remove_seg(recorder, seg.into()); - self.recording_geometry_with_rtree - .remove_dot(recorder, seg_to.into()); - })?; - - Ok(Cane { - seg, - dot: seg_to, - bend, - }) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() - 4))] - pub fn remove_cane( - &mut self, - recorder: &mut DrawingEdit, - cane: &Cane, - face: LooseDotIndex, - ) { - let maybe_outer = self.primitive(cane.bend).outer(); - - // Removing a loose bend affects its outer bends. - if let Some(outer) = maybe_outer { - self.reattach_bend(recorder, outer, self.primitive(cane.bend).inner()); - } - - self.recording_geometry_with_rtree - .remove_bend(recorder, cane.bend.into()); - self.recording_geometry_with_rtree - .remove_seg(recorder, cane.seg.into()); - - // We must remove the dots only after the segs and bends because we need dots to calculate - // the shapes, which we first need unchanged to remove the segs and bends from the R-tree. - - self.recording_geometry_with_rtree - .remove_dot(recorder, face.into()); - self.recording_geometry_with_rtree - .remove_dot(recorder, cane.dot.into()); - - if let Some(outer) = maybe_outer { - self.update_this_and_outward_bows(recorder, outer).unwrap(); // Must never fail. - } + #[inline(always)] + fn graph( + &self, + ) -> &petgraph::stable_graph::StableDiGraph< + GenericNode, + GeometryLabel, + usize, + > { + self.geometry_with_rtree.graph() } pub fn cane(&self, dot: LooseDotIndex) -> Cane { Cane::from_dot(dot, self) } - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn move_dot( - &mut self, - recorder: &mut DrawingEdit, - dot: DotIndex, - to: Point, - ) -> Result<(), Infringement> { - match dot { - DotIndex::Fixed(..) => self.move_dot_with_infringables(recorder, dot, to, Some(&[])), - DotIndex::Loose(..) => self.move_dot_with_infringables(recorder, dot, to, Some(&[])), - } - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn move_dot_with_infringables( - &mut self, - recorder: &mut DrawingEdit, - dot: DotIndex, - to: Point, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result<(), Infringement> { - let old_pos = self - .recording_geometry_with_rtree - .geometry() - .dot_weight(dot) - .pos(); - self.recording_geometry_with_rtree - .move_dot(recorder, dot, to); - - for limb in dot.primitive(self).limbs() { - if let Some(infringement) = self.detect_infringement_except(limb, infringables) { - // Restore original state. - self.recording_geometry_with_rtree - .move_dot(recorder, dot, old_pos); - return Err(infringement); - } - } - - if let Some(infringement) = self.detect_infringement_except(dot.into(), infringables) { - // Restore original state. - self.recording_geometry_with_rtree - .move_dot(recorder, dot, old_pos); - return Err(infringement); - } - - Ok(()) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn shift_bend_with_infringables( - &mut self, - recorder: &mut DrawingEdit, - bend: BendIndex, - offset: f64, - infringables: Option<&[PrimitiveIndex]>, - ) -> Result<(), Infringement> { - let old_offset = self - .recording_geometry_with_rtree - .geometry() - .bend_weight(bend) - .offset(); - self.recording_geometry_with_rtree - .shift_bend(recorder, bend, offset); - - if let Some(infringement) = self.detect_infringement_except(bend.into(), infringables) { - // Restore original state. - self.recording_geometry_with_rtree - .shift_bend(recorder, bend, old_offset); - return Err(infringement); - } - - Ok(()) - } - fn detect_collision(&self, node: PrimitiveIndex) -> Option { let shape = node.primitive(self).shape(); - self.recording_geometry_with_rtree + self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting(&shape.full_height_envelope_3d(0.0, 2)) .filter_map(|wrapper| { @@ -843,80 +157,6 @@ impl Drawing { .find(|primitive_node| shape.intersects(&primitive_node.primitive(self).shape())) .map(|collidee| Collision(shape, collidee)) } -} - -impl Drawing { - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - fn add_dot_infringably + GetLayer>( - &mut self, - recorder: &mut DrawingEdit, - weight: W, - ) -> GenericIndex - where - GenericIndex: Into + Copy, - { - self.recording_geometry_with_rtree.add_dot(recorder, weight) - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() + 1))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count() + 2))] - fn add_seg_infringably + GetLayer>( - &mut self, - recorder: &mut DrawingEdit, - from: DotIndex, - to: DotIndex, - weight: W, - ) -> GenericIndex - where - GenericIndex: Into, - { - self.recording_geometry_with_rtree - .add_seg(recorder, from, to, weight) - } - - pub fn add_compound(&mut self, recorder: &mut DrawingEdit, weight: CW) -> GenericIndex { - self.recording_geometry_with_rtree - .add_compound(recorder, weight) - } - - pub fn remove_compound(&mut self, recorder: &mut DrawingEdit, compound: GenericIndex) { - self.recording_geometry_with_rtree - .remove_compound(recorder, compound); - } - - pub fn add_to_compound( - &mut self, - recorder: &mut DrawingEdit, - primitive: GenericIndex, - compound: GenericIndex, - ) { - self.recording_geometry_with_rtree - .add_to_compound(recorder, primitive, compound); - } - - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(ret.is_ok() -> self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - #[debug_ensures(ret.is_err() -> self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count() - 1))] - fn fail_and_remove_if_infringes_except( - &mut self, - recorder: &mut DrawingEdit, - node: PrimitiveIndex, - maybe_except: Option<&[PrimitiveIndex]>, - ) -> Result<(), Infringement> { - if let Some(infringement) = self.detect_infringement_except(node, maybe_except) { - if let Ok(dot) = node.try_into() { - self.recording_geometry_with_rtree.remove_dot(recorder, dot); - } else if let Ok(seg) = node.try_into() { - self.recording_geometry_with_rtree.remove_seg(recorder, seg); - } else if let Ok(bend) = node.try_into() { - self.recording_geometry_with_rtree - .remove_bend(recorder, bend); - } - return Err(infringement); - } - Ok(()) - } fn detect_infringement_except( &self, @@ -950,7 +190,7 @@ impl Drawing { .unwrap_or(0.0), ); - self.recording_geometry_with_rtree + self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting( &limiting_shape.envelope_3d(0.0, node.primitive(self).layer()), @@ -983,7 +223,7 @@ impl Drawing { } pub fn primitive_nodes(&self) -> impl Iterator + '_ { - self.recording_geometry_with_rtree + self.geometry_with_rtree .rtree() .iter() .filter_map(|wrapper| { @@ -996,7 +236,7 @@ impl Drawing { } pub fn layer_primitive_nodes(&self, layer: usize) -> impl Iterator + '_ { - self.recording_geometry_with_rtree + self.geometry_with_rtree .rtree() .locate_in_envelope_intersecting(&AABB::from_corners( [-f64::INFINITY, -f64::INFINITY, layer as f64], @@ -1012,14 +252,14 @@ impl Drawing { } pub fn compound_weight(&self, compound: GenericIndex) -> CW { - self.recording_geometry_with_rtree.compound_weight(compound) + self.geometry_with_rtree.compound_weight(compound) } pub fn compounds<'a, W: 'a>( &'a self, node: GenericIndex, ) -> impl Iterator> + 'a { - self.recording_geometry_with_rtree.compounds(node) + self.geometry_with_rtree.compounds(node) } fn are_connectable(&self, node1: PrimitiveIndex, node2: PrimitiveIndex) -> bool { @@ -1046,17 +286,11 @@ impl Drawing { SegIndex, BendIndex, > { - self.recording_geometry_with_rtree.geometry() + self.geometry_with_rtree.geometry() } pub fn rtree(&self) -> &RTree>>> { - self.recording_geometry_with_rtree.rtree() - } - - #[debug_ensures(self.recording_geometry_with_rtree.graph().node_count() == old(self.recording_geometry_with_rtree.graph().node_count()))] - #[debug_ensures(self.recording_geometry_with_rtree.graph().edge_count() == old(self.recording_geometry_with_rtree.graph().edge_count()))] - pub fn rules_mut(&mut self) -> &mut R { - &mut self.rules + self.geometry_with_rtree.rtree() } pub fn guide(&self) -> Guide { @@ -1076,11 +310,11 @@ impl Drawing { } pub fn layer_count(&self) -> usize { - self.recording_geometry_with_rtree.layer_count() + *self.geometry_with_rtree.layer_count() } pub fn node_count(&self) -> usize { - self.recording_geometry_with_rtree.graph().node_count() + self.geometry_with_rtree.graph().node_count() } fn test_if_looses_dont_infringe_each_other(&self) -> bool { @@ -1119,6 +353,713 @@ impl Drawing { .is_some() }) } + + pub fn rules_mut(&mut self) -> &mut R { + &mut self.rules + } +} + +impl RecordingDrawing<'_, CW, R> { + fn recording_geometry_with_rtree( + &mut self, + ) -> RecordingGeometryWithRtree< + '_, + PrimitiveWeight, + DotWeight, + SegWeight, + BendWeight, + CW, + PrimitiveIndex, + DotIndex, + SegIndex, + BendIndex, + > { + self.drawing.geometry_with_rtree.recording(self.recorder) + } + + pub fn remove_band(&mut self, band: BandTermsegIndex) -> Result<(), DrawingException> { + match band { + BandTermsegIndex::Straight(seg) => { + self.recording_geometry_with_rtree().remove_seg(seg.into()); + } + BandTermsegIndex::Bended(first_loose_seg) => { + let mut dots = vec![]; + let mut segs = vec![]; + let mut bends = vec![]; + let mut outers = vec![]; + + let mut maybe_loose = Some(first_loose_seg.into()); + let mut prev = None; + + while let Some(loose) = maybe_loose { + match loose { + LooseIndex::Dot(dot) => { + dots.push(dot); + } + LooseIndex::LoneSeg(seg) => { + self.recording_geometry_with_rtree().remove_seg(seg.into()); + break; + } + LooseIndex::SeqSeg(seg) => { + segs.push(seg); + } + LooseIndex::Bend(bend) => { + bends.push(bend); + + if let Some(outer) = self.drawing.primitive(bend).outer() { + outers.push(outer); + self.reattach_bend(outer, self.drawing.primitive(bend).inner()); + } + } + } + + let prev_prev = prev; + prev = maybe_loose; + maybe_loose = self.drawing.loose(loose).next_loose(prev_prev); + } + + for bend in bends { + self.recording_geometry_with_rtree() + .remove_bend(bend.into()); + } + + for seg in segs { + self.recording_geometry_with_rtree().remove_seg(seg.into()); + } + + // We must remove the dots only after the segs and bends because we need dots to calculate + // the shapes, which we first need unchanged to remove the segs and bends from the R-tree. + + for dot in dots { + self.recording_geometry_with_rtree().remove_dot(dot.into()); + } + + for outer in outers { + self.update_this_and_outward_bows(outer)?; + } + } + } + + Ok(()) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result { + self.add_dot_with_infringables(weight, Some(&[])) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 1))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn remove_fixed_dot(&mut self, dot: FixedDotIndex) { + self.recording_geometry_with_rtree().remove_dot(dot.into()); + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_fixed_dot_infringably(&mut self, weight: FixedDotWeight) -> FixedDotIndex { + self.add_dot_infringably(weight) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + fn add_dot_with_infringables + GetLayer>( + &mut self, + weight: W, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result, Infringement> + where + GenericIndex: Into + Copy, + { + let dot = self.add_dot_infringably(weight); + self.fail_and_remove_if_infringes_except(dot.into(), infringables)?; + + Ok(dot) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_fixed_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + ) -> Result { + self.add_seg_with_infringables(from.into(), to.into(), weight, Some(&[])) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] + pub fn add_fixed_seg_infringably( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + ) -> FixedSegIndex { + self.add_seg_infringably(from.into(), to.into(), weight) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_lone_loose_seg( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: LoneLooseSegWeight, + ) -> Result { + let seg = self.add_seg_with_infringables(from.into(), to.into(), weight, Some(&[]))?; + Ok(seg) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_seq_loose_seg( + &mut self, + from: DotIndex, + to: LooseDotIndex, + weight: SeqLooseSegWeight, + ) -> Result { + let seg = self.add_seg_with_infringables(from, to.into(), weight, Some(&[]))?; + Ok(seg) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 2))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_seg_with_infringables + GetLayer>( + &mut self, + from: DotIndex, + to: DotIndex, + weight: W, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result, Infringement> + where + GenericIndex: Into + Copy, + { + let seg = self.add_seg_infringably(from, to, weight); + self.fail_and_remove_if_infringes_except(seg.into(), infringables)?; + + Ok(seg) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 3) + || self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 4))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_loose_bend_with_infringables( + &mut self, + from: LooseDotIndex, + to: LooseDotIndex, + around: GearIndex, + weight: LooseBendWeight, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result { + // It makes no sense to wrap something around or under one of its connectables. + // + if let Some(net) = weight.maybe_net { + if let Some(around_net) = around.primitive(self.drawing).maybe_net() { + if net == around_net { + return Err(AlreadyConnected(net, around.into()).into()); + } + } + // + if let Some(next_gear) = around.ref_(self.drawing).next_gear() { + if let Some(next_gear_net) = next_gear.primitive(self.drawing).maybe_net() { + if net == next_gear_net { + return Err(AlreadyConnected(net, next_gear.into()).into()); + } + } + } + } + + match around { + GearIndex::FixedDot(core) => self + .add_core_bend_with_infringables(from.into(), to.into(), core, weight, infringables) + .map_err(Into::into), + GearIndex::FixedBend(around) => self + .add_outer_bend_with_infringables(from, to, around.into(), weight, infringables) + .map_err(Into::into), + GearIndex::LooseBend(around) => self + .add_outer_bend_with_infringables(from, to, around.into(), weight, infringables) + .map_err(Into::into), + } + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 3))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_core_bend_with_infringables + GetLayer>( + &mut self, + from: DotIndex, + to: DotIndex, + core: FixedDotIndex, + weight: W, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result, Infringement> + where + GenericIndex: Into + Copy, + { + let bend = self + .recording_geometry_with_rtree() + .add_bend(from, to, core.into(), weight); + + self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; + Ok(bend) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 4))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_outer_bend_with_infringables( + &mut self, + from: LooseDotIndex, + to: LooseDotIndex, + inner: BendIndex, + weight: LooseBendWeight, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result, Infringement> { + let core = *self + .drawing + .graph() + .neighbors(inner.petgraph_index()) + .filter(|ni| { + matches!( + self.drawing + .graph() + .edge_weight( + self.drawing + .graph() + .find_edge(inner.petgraph_index(), *ni) + .unwrap() + ) + .unwrap(), + GeometryLabel::Core + ) + }) + .map(FixedDotIndex::new) + .collect::>() + .first() + .unwrap(); + + let bend = self.recording_geometry_with_rtree().add_bend( + from.into(), + to.into(), + core.into(), + weight, + ); + self.recording_geometry_with_rtree() + .reattach_bend(bend.into(), Some(inner)); + + self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; + Ok(bend) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn flip_bend(&mut self, bend: FixedBendIndex) { + self.recording_geometry_with_rtree().flip_bend(bend.into()); + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()) + || self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() - 1) + || self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 1))] + fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option) { + self.recording_geometry_with_rtree() + .reattach_bend(bend.into(), maybe_new_inner.map(Into::into)); + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn insert_cane( + &mut self, + from: DotIndex, + around: GearIndex, + dot_weight: LooseDotWeight, + seg_weight: SeqLooseSegWeight, + bend_weight: LooseBendWeight, + cw: bool, + ) -> Result { + let maybe_next_gear = around.ref_(self.drawing).next_gear(); + let cane = self.add_cane_with_infringables( + from, + around, + dot_weight, + seg_weight, + bend_weight, + cw, + Some(&[]), + )?; + + if let Some(next_gear) = maybe_next_gear { + self.reattach_bend(next_gear, Some(cane.bend)); + } + + if let Some(outer) = self.drawing.primitive(cane.bend).outer() { + self.update_this_and_outward_bows(outer).inspect_err(|_| { + let joint = self.drawing.primitive(cane.bend).other_joint(cane.dot); + self.remove_cane(&cane, joint); + })?; + } + + // Segs must not cross. + if let Some(collision) = self.drawing.detect_collision(cane.seg.into()) { + let joint = self.drawing.primitive(cane.bend).other_joint(cane.dot); + self.remove_cane(&cane, joint); + Err(collision.into()) + } else { + Ok(cane) + } + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn update_this_and_outward_bows( + &mut self, + around: LooseBendIndex, + ) -> Result<(), DrawingException> { + // FIXME: Fail gracefully on infringement. + let mut maybe_rail = Some(around); + + while let Some(rail) = maybe_rail { + let rail_primitive = self.drawing.primitive(rail); + let joints = rail_primitive.joints(); + + let guide = Guide::new(self.drawing); + let from_head = guide.rear_head(joints.1); + let to_head = guide.rear_head(joints.0); + + if let Some(inner) = rail_primitive.inner() { + let from = guide + .head_around_bend_segment( + &from_head, + inner.into(), + true, + self.drawing.primitive(rail).width(), + )? + .end_point(); + let to = guide + .head_around_bend_segment( + &to_head, + inner.into(), + false, + self.drawing.primitive(rail).width(), + )? + .end_point(); + let offset = guide.head_around_bend_offset( + &from_head, + inner.into(), + self.drawing.primitive(rail).width(), + ); + + self.move_dot_with_infringables( + joints.0.into(), + from, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + self.move_dot_with_infringables( + joints.1.into(), + to, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + + self.shift_bend_with_infringables( + rail.into(), + offset, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + + // Update offsets in case the rule conditions changed. + } else { + let core = rail_primitive.core(); + let from = guide + .head_around_dot_segment( + &from_head, + core.into(), + true, + self.drawing.primitive(rail).width(), + )? + .end_point(); + let to = guide + .head_around_dot_segment( + &to_head, + core.into(), + false, + self.drawing.primitive(rail).width(), + )? + .end_point(); + let offset = guide.head_around_dot_offset( + &from_head, + core.into(), + self.drawing.primitive(rail).width(), + ); + + self.move_dot_with_infringables( + joints.0.into(), + from, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + self.move_dot_with_infringables( + joints.1.into(), + to, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + + self.shift_bend_with_infringables( + rail.into(), + offset, + Some(&self.drawing.collect().bend_outer_bows(rail)), + )?; + } + + maybe_rail = self.drawing.primitive(rail).outer(); + } + + Ok(()) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn add_cane( + &mut self, + from: DotIndex, + around: GearIndex, + dot_weight: LooseDotWeight, + seg_weight: SeqLooseSegWeight, + bend_weight: LooseBendWeight, + cw: bool, + ) -> Result { + self.add_cane_with_infringables( + from, + around, + dot_weight, + seg_weight, + bend_weight, + cw, + Some(&[]), + ) + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_cane_with_infringables( + &mut self, + from: DotIndex, + around: GearIndex, + dot_weight: LooseDotWeight, + seg_weight: SeqLooseSegWeight, + bend_weight: LooseBendWeight, + cw: bool, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result { + let seg_to = self.add_dot_with_infringables(dot_weight, infringables)?; + let seg = self + .add_seg_with_infringables(from, seg_to.into(), seg_weight, infringables) + .inspect_err(|_| { + self.recording_geometry_with_rtree() + .remove_dot(seg_to.into()); + })?; + + let to = self + .add_dot_with_infringables(dot_weight, infringables) + .inspect_err(|_| { + self.recording_geometry_with_rtree().remove_seg(seg.into()); + self.recording_geometry_with_rtree() + .remove_dot(seg_to.into()); + })?; + + let (bend_from, bend_to) = if cw { (to, seg_to) } else { (seg_to, to) }; + + let bend = self + .add_loose_bend_with_infringables(bend_from, bend_to, around, bend_weight, infringables) + .inspect_err(|_| { + let mut recording_geometry_with_rtree = self.recording_geometry_with_rtree(); + recording_geometry_with_rtree.remove_dot(to.into()); + recording_geometry_with_rtree.remove_seg(seg.into()); + recording_geometry_with_rtree.remove_dot(seg_to.into()); + })?; + + Ok(Cane { + seg, + dot: seg_to, + bend, + }) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 4))] + pub fn remove_cane(&mut self, cane: &Cane, face: LooseDotIndex) { + let maybe_outer = self.drawing.primitive(cane.bend).outer(); + + // Removing a loose bend affects its outer bends. + if let Some(outer) = maybe_outer { + self.reattach_bend(outer, self.drawing.primitive(cane.bend).inner()); + } + + self.recording_geometry_with_rtree() + .remove_bend(cane.bend.into()); + self.recording_geometry_with_rtree() + .remove_seg(cane.seg.into()); + + // We must remove the dots only after the segs and bends because we need dots to calculate + // the shapes, which we first need unchanged to remove the segs and bends from the R-tree. + + self.recording_geometry_with_rtree().remove_dot(face.into()); + self.recording_geometry_with_rtree() + .remove_dot(cane.dot.into()); + + if let Some(outer) = maybe_outer { + self.update_this_and_outward_bows(outer).unwrap(); // Must never fail. + } + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { + match dot { + DotIndex::Fixed(..) => self.move_dot_with_infringables(dot, to, Some(&[])), + DotIndex::Loose(..) => self.move_dot_with_infringables(dot, to, Some(&[])), + } + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn move_dot_with_infringables( + &mut self, + dot: DotIndex, + to: Point, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result<(), Infringement> { + let old_pos = self.drawing.geometry().dot_weight(dot).pos(); + self.recording_geometry_with_rtree().move_dot(dot, to); + + for limb in dot.primitive(self.drawing).limbs() { + if let Some(infringement) = self.drawing.detect_infringement_except(limb, infringables) + { + // Restore original state. + self.recording_geometry_with_rtree().move_dot(dot, old_pos); + return Err(infringement); + } + } + + if let Some(infringement) = self + .drawing + .detect_infringement_except(dot.into(), infringables) + { + // Restore original state. + self.recording_geometry_with_rtree().move_dot(dot, old_pos); + return Err(infringement); + } + + Ok(()) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn shift_bend_with_infringables( + &mut self, + bend: BendIndex, + offset: f64, + infringables: Option<&[PrimitiveIndex]>, + ) -> Result<(), Infringement> { + let old_offset = self.drawing.geometry().bend_weight(bend).offset(); + self.recording_geometry_with_rtree() + .shift_bend(bend, offset); + + if let Some(infringement) = self + .drawing + .detect_infringement_except(bend.into(), infringables) + { + // Restore original state. + self.recording_geometry_with_rtree() + .shift_bend(bend, old_offset); + return Err(infringement); + } + + Ok(()) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + fn add_dot_infringably + GetLayer>( + &mut self, + weight: W, + ) -> GenericIndex + where + GenericIndex: Into + Copy, + { + self.recording_geometry_with_rtree().add_dot(weight) + } + + #[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] + #[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] + fn add_seg_infringably + GetLayer>( + &mut self, + from: DotIndex, + to: DotIndex, + weight: W, + ) -> GenericIndex + where + GenericIndex: Into, + { + self.recording_geometry_with_rtree() + .add_seg(from, to, weight) + } + + pub fn add_compound(&mut self, weight: CW) -> GenericIndex { + self.recording_geometry_with_rtree().add_compound(weight) + } + + pub fn remove_compound(&mut self, compound: GenericIndex) { + self.recording_geometry_with_rtree() + .remove_compound(compound); + } + + pub fn add_to_compound(&mut self, primitive: GenericIndex, compound: GenericIndex) { + self.recording_geometry_with_rtree() + .add_to_compound(primitive, compound); + } + + #[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] + #[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] + #[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 1))] + fn fail_and_remove_if_infringes_except( + &mut self, + node: PrimitiveIndex, + maybe_except: Option<&[PrimitiveIndex]>, + ) -> Result<(), Infringement> { + if let Some(infringement) = self.drawing.detect_infringement_except(node, maybe_except) { + let mut recording_geometry_with_rtree = self.recording_geometry_with_rtree(); + if let Ok(dot) = node.try_into() { + recording_geometry_with_rtree.remove_dot(dot); + } else if let Ok(seg) = node.try_into() { + recording_geometry_with_rtree.remove_seg(seg); + } else if let Ok(bend) = node.try_into() { + recording_geometry_with_rtree.remove_bend(bend); + } + return Err(infringement); + } + Ok(()) + } + + pub fn rules_mut(&mut self) -> &mut R { + &mut self.drawing.rules + } } impl @@ -1134,7 +1075,27 @@ impl BendIndex, > for Drawing { + #[inline] fn apply(&mut self, edit: &DrawingEdit) { - self.recording_geometry_with_rtree.apply(edit); + self.geometry_with_rtree.apply(edit); + } +} + +impl + ApplyGeometryEdit< + PrimitiveWeight, + DotWeight, + SegWeight, + BendWeight, + CW, + PrimitiveIndex, + DotIndex, + SegIndex, + BendIndex, + > for RecordingDrawing<'_, CW, R> +{ + #[inline] + fn apply(&mut self, edit: &DrawingEdit) { + self.drawing.geometry_with_rtree.apply(edit); } } diff --git a/src/geometry/recording_with_rtree.rs b/src/geometry/recording_with_rtree.rs index 39903f6..55553e0 100644 --- a/src/geometry/recording_with_rtree.rs +++ b/src/geometry/recording_with_rtree.rs @@ -23,8 +23,9 @@ use super::{ }; #[derive(Debug)] -pub struct RecordingGeometryWithRtree { - geometry_with_rtree: GeometryWithRtree, +pub struct RecordingGeometryWithRtree<'a, PW, DW, SW, BW, CW, PI, DI, SI, BI> { + pub geometry_with_rtree: &'a mut GeometryWithRtree, + pub recorder: &'a mut GeometryEdit, } impl< @@ -37,26 +38,14 @@ impl< DI: GetPetgraphIndex + Into + Eq + Hash + Copy, SI: GetPetgraphIndex + Into + Eq + Hash + Copy, BI: GetPetgraphIndex + Into + Eq + Hash + Copy, - > RecordingGeometryWithRtree + > RecordingGeometryWithRtree<'_, PW, DW, SW, BW, CW, PI, DI, SI, BI> { - pub fn new(layer_count: usize) -> Self { - Self { - geometry_with_rtree: GeometryWithRtree::::new( - layer_count, - ), - } - } - - pub fn add_dot + GetLayer>( - &mut self, - recorder: &mut GeometryEdit, - weight: W, - ) -> GenericIndex + pub fn add_dot + GetLayer>(&mut self, weight: W) -> GenericIndex where GenericIndex: Into, { let dot = self.geometry_with_rtree.add_dot(weight); - recorder.dots.insert( + self.recorder.dots.insert( Into::::into(dot) .try_into() .unwrap_or_else(|_| unreachable!()), @@ -70,7 +59,6 @@ impl< pub fn add_seg + GetLayer>( &mut self, - recorder: &mut GeometryEdit, from: DI, to: DI, weight: W, @@ -79,7 +67,7 @@ impl< GenericIndex: Into, { let seg = self.geometry_with_rtree.add_seg(from, to, weight); - recorder.segs.insert( + self.recorder.segs.insert( Into::::into(seg) .try_into() .unwrap_or_else(|_| unreachable!()), @@ -96,7 +84,6 @@ impl< pub fn add_bend + GetLayer>( &mut self, - recorder: &mut GeometryEdit, from: DI, to: DI, core: DI, @@ -106,7 +93,7 @@ impl< GenericIndex: Into, { let bend = self.geometry_with_rtree.add_bend(from, to, core, weight); - recorder.bends.insert( + self.recorder.bends.insert( Into::::into(bend) .try_into() .unwrap_or_else(|_| unreachable!()), @@ -121,24 +108,15 @@ impl< bend } - pub fn add_compound( - &mut self, - recorder: &mut GeometryEdit, - weight: CW, - ) -> GenericIndex { + pub fn add_compound(&mut self, weight: CW) -> GenericIndex { let compound = self.geometry_with_rtree.add_compound(weight); - recorder + self.recorder .compounds .insert(compound, (None, Some((vec![], weight)))); compound } - pub fn add_to_compound( - &mut self, - recorder: &mut GeometryEdit, - primitive: GenericIndex, - compound: GenericIndex, - ) { + pub fn add_to_compound(&mut self, primitive: GenericIndex, compound: GenericIndex) { let geometry = self.geometry_with_rtree.geometry(); let old_members = geometry.compound_members(compound).collect(); let old_weight = geometry.compound_weight(compound); @@ -150,88 +128,63 @@ impl< let new_members = geometry.compound_members(compound).collect(); let new_weight = geometry.compound_weight(compound); - recorder + self.recorder .compounds .entry(compound) .or_insert((Some((old_members, old_weight)), None)) .1 = Some((new_members, new_weight)); } - pub fn remove_dot( - &mut self, - recorder: &mut GeometryEdit, - dot: DI, - ) -> Result<(), ()> { + pub fn remove_dot(&mut self, dot: DI) -> Result<(), ()> { let weight = self.geometry_with_rtree.geometry().dot_weight(dot); self.geometry_with_rtree.remove_dot(dot)?; - edit_remove_from_map(&mut recorder.dots, dot, weight); + edit_remove_from_map(&mut self.recorder.dots, dot, weight); Ok(()) } - pub fn remove_seg( - &mut self, - recorder: &mut GeometryEdit, - seg: SI, - ) { + pub fn remove_seg(&mut self, seg: SI) { let geometry = self.geometry_with_rtree.geometry(); let weight = geometry.seg_weight(seg); let joints = geometry.seg_joints(seg); self.geometry_with_rtree.remove_seg(seg); - edit_remove_from_map(&mut recorder.segs, seg, (joints, weight)); + edit_remove_from_map(&mut self.recorder.segs, seg, (joints, weight)); } - pub fn remove_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - ) { + pub fn remove_bend(&mut self, bend: BI) { let geometry = self.geometry_with_rtree.geometry(); let weight = geometry.bend_weight(bend); let joints = geometry.bend_joints(bend); let core = geometry.core(bend); self.geometry_with_rtree.remove_bend(bend); edit_remove_from_map( - &mut recorder.bends, + &mut self.recorder.bends, bend, ((joints.0, joints.1, core), weight), ); } - pub fn remove_compound( - &mut self, - recorder: &mut GeometryEdit, - compound: GenericIndex, - ) { + pub fn remove_compound(&mut self, compound: GenericIndex) { let geometry = self.geometry_with_rtree.geometry(); let weight = geometry.compound_weight(compound); let members = geometry.compound_members(compound).collect(); self.geometry_with_rtree.remove_compound(compound); - edit_remove_from_map(&mut recorder.compounds, compound, (members, weight)); + edit_remove_from_map(&mut self.recorder.compounds, compound, (members, weight)); } - pub fn move_dot( - &mut self, - recorder: &mut GeometryEdit, - dot: DI, - to: Point, - ) { + pub fn move_dot(&mut self, dot: DI, to: Point) { let old_weight = self.geometry_with_rtree.geometry().dot_weight(dot); self.geometry_with_rtree.move_dot(dot, to); let new_weight = self.geometry_with_rtree.geometry().dot_weight(dot); - recorder + self.recorder .dots .entry(dot) .or_insert((Some(old_weight), None)) .1 = Some(new_weight); } - fn modify_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - f: F, - ) where + fn modify_bend(&mut self, bend: BI, f: F) + where F: FnOnce(&mut GeometryWithRtree, BI), { let geometry = self.geometry_with_rtree.geometry(); @@ -246,7 +199,7 @@ impl< let new_core = geometry.core(bend); let new_weight = geometry.bend_weight(bend); - recorder + self.recorder .bends .entry(bend) .or_insert(( @@ -256,34 +209,20 @@ impl< .1 = Some(((new_joints.0, new_joints.1, new_core), new_weight)); } - pub fn shift_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - offset: f64, - ) { - self.modify_bend(recorder, bend, |geometry_with_rtree, bend| { + pub fn shift_bend(&mut self, bend: BI, offset: f64) { + self.modify_bend(bend, |geometry_with_rtree, bend| { geometry_with_rtree.shift_bend(bend, offset) }); } - pub fn flip_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - ) { - self.modify_bend(recorder, bend, |geometry_with_rtree, bend| { + pub fn flip_bend(&mut self, bend: BI) { + self.modify_bend(bend, |geometry_with_rtree, bend| { geometry_with_rtree.flip_bend(bend) }); } - pub fn reattach_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - maybe_new_inner: Option, - ) { - self.modify_bend(recorder, bend, |geometry_with_rtree, bend| { + pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option) { + self.modify_bend(bend, |geometry_with_rtree, bend| { geometry_with_rtree.reattach_bend(bend, maybe_new_inner) }); } @@ -299,6 +238,10 @@ impl< self.geometry_with_rtree.compounds(node) } + pub fn recorder(&self) -> &GeometryEdit { + &*self.recorder + } + pub fn geometry(&self) -> &Geometry { self.geometry_with_rtree.geometry() } @@ -349,65 +292,10 @@ impl< SI: GetPetgraphIndex + Into + Eq + Hash + Copy, BI: GetPetgraphIndex + Into + Eq + Hash + Copy, > ApplyGeometryEdit - for RecordingGeometryWithRtree + for RecordingGeometryWithRtree<'_, PW, DW, SW, BW, CW, PI, DI, SI, BI> { + #[inline(always)] fn apply(&mut self, edit: &GeometryEdit) { - for (compound, (maybe_old_data, ..)) in &edit.compounds { - if maybe_old_data.is_some() { - self.geometry_with_rtree.remove_compound(*compound); - } - } - - for (bend, (maybe_old_data, ..)) in &edit.bends { - if maybe_old_data.is_some() { - self.geometry_with_rtree.remove_bend(*bend); - } - } - - for (seg, (maybe_old_data, ..)) in &edit.segs { - if maybe_old_data.is_some() { - self.geometry_with_rtree.remove_seg(*seg); - } - } - - for (dot, (maybe_old_data, ..)) in &edit.dots { - if maybe_old_data.is_some() { - self.geometry_with_rtree.remove_dot(*dot); - } - } - - for (dot, (.., maybe_new_data)) in &edit.dots { - if let Some(weight) = maybe_new_data { - self.geometry_with_rtree.add_dot_at_index(*dot, *weight); - } - } - - for (seg, (.., maybe_new_data)) in &edit.segs { - if let Some(((from, to), weight)) = maybe_new_data { - self.geometry_with_rtree - .add_seg_at_index(*seg, *from, *to, *weight); - } - } - - for (bend, (.., maybe_new_data)) in &edit.bends { - if let Some(((from, to, core), weight)) = maybe_new_data { - self.geometry_with_rtree - .add_bend_at_index(*bend, *from, *to, *core, *weight); - } - } - - for (compound, (.., maybe_new_data)) in &edit.compounds { - if let Some((members, weight)) = maybe_new_data { - self.geometry_with_rtree - .add_compound_at_index(*compound, *weight); - - for member in members { - self.geometry_with_rtree.add_to_compound( - GenericIndex::::new(member.petgraph_index()), - *compound, - ); - } - } - } + self.geometry_with_rtree.apply(edit) } } diff --git a/src/geometry/with_rtree.rs b/src/geometry/with_rtree.rs index 6274dde..cee4dee 100644 --- a/src/geometry/with_rtree.rs +++ b/src/geometry/with_rtree.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: MIT use contracts_try::debug_invariant; +use core::hash::Hash; use derive_getters::Getters; use geo::Point; use petgraph::stable_graph::StableDiGraph; @@ -12,6 +13,7 @@ use crate::{ drawing::graph::{GetLayer, Retag}, geometry::{ compound::ManageCompounds, + edit::{ApplyGeometryEdit, GeometryEdit}, primitive::{AccessPrimitiveShape, PrimitiveShape}, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, GetWidth, @@ -68,6 +70,28 @@ impl< } } + #[inline(always)] + pub fn recording<'a>( + &'a mut self, + recorder: &'a mut super::edit::GeometryEdit, + ) -> super::recording_with_rtree::RecordingGeometryWithRtree< + 'a, + PW, + DW, + SW, + BW, + CW, + PI, + DI, + SI, + BI, + > { + super::recording_with_rtree::RecordingGeometryWithRtree { + geometry_with_rtree: self, + recorder, + } + } + pub fn add_dot + GetLayer>(&mut self, weight: W) -> GenericIndex where GenericIndex: Into, @@ -424,3 +448,74 @@ impl< self.geometry.compounds(node) } } + +impl< + PW: GetWidth + GetLayer + TryInto + TryInto + TryInto + Retag + Copy, + DW: AccessDotWeight + GetLayer, + SW: AccessSegWeight + GetLayer, + BW: AccessBendWeight + GetLayer, + CW: Copy, + PI: GetPetgraphIndex + TryInto + TryInto + TryInto + Eq + Hash + Copy, + DI: GetPetgraphIndex + Into + Eq + Hash + Copy, + SI: GetPetgraphIndex + Into + Eq + Hash + Copy, + BI: GetPetgraphIndex + Into + Eq + Hash + Copy, + > ApplyGeometryEdit + for GeometryWithRtree +{ + fn apply(&mut self, edit: &GeometryEdit) { + for (compound, (maybe_old_data, ..)) in &edit.compounds { + if maybe_old_data.is_some() { + self.remove_compound(*compound); + } + } + + for (bend, (maybe_old_data, ..)) in &edit.bends { + if maybe_old_data.is_some() { + self.remove_bend(*bend); + } + } + + for (seg, (maybe_old_data, ..)) in &edit.segs { + if maybe_old_data.is_some() { + self.remove_seg(*seg); + } + } + + for (dot, (maybe_old_data, ..)) in &edit.dots { + if maybe_old_data.is_some() { + self.remove_dot(*dot); + } + } + + for (dot, (.., maybe_new_data)) in &edit.dots { + if let Some(weight) = maybe_new_data { + self.add_dot_at_index(*dot, *weight); + } + } + + for (seg, (.., maybe_new_data)) in &edit.segs { + if let Some(((from, to), weight)) = maybe_new_data { + self.add_seg_at_index(*seg, *from, *to, *weight); + } + } + + for (bend, (.., maybe_new_data)) in &edit.bends { + if let Some(((from, to, core), weight)) = maybe_new_data { + self.add_bend_at_index(*bend, *from, *to, *core, *weight); + } + } + + for (compound, (.., maybe_new_data)) in &edit.compounds { + if let Some((members, weight)) = maybe_new_data { + self.add_compound_at_index(*compound, *weight); + + for member in members { + self.add_to_compound( + GenericIndex::::new(member.petgraph_index()), + *compound, + ); + } + } + } + } +} diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 8279f03..e5a1b24 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -70,8 +70,7 @@ impl Layout { bend_weight: LooseBendWeight, cw: bool, ) -> Result { - self.drawing.insert_cane( - recorder, + self.drawing.recording(recorder).insert_cane( from, around, dot_weight, @@ -83,7 +82,7 @@ impl Layout { /// Remove [`Cane`] object from the [`Layout`] pub fn remove_cane(&mut self, recorder: &mut LayoutEdit, cane: &Cane, face: LooseDotIndex) { - self.drawing.remove_cane(recorder, cane, face) + 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)] @@ -94,29 +93,31 @@ impl Layout { recorder: &mut LayoutEdit, weight: ViaWeight, ) -> Result, Infringement> { - let compound = self.drawing.add_compound(recorder, weight.into()); + 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.add_fixed_dot( - recorder, - FixedDotWeight { + match self + .drawing + .recording(recorder) + .add_fixed_dot(FixedDotWeight { circle: weight.circle, layer, maybe_net: weight.maybe_net, - }, - ) { + }) { Ok(dot) => { - self.drawing.add_to_compound(recorder, dot, compound); + self.drawing + .recording(recorder) + .add_to_compound(dot, compound); dots.push(dot); } Err(err) => { // Remove inserted dots. - self.drawing.remove_compound(recorder, compound); + self.drawing.recording(recorder).remove_compound(compound); for dot in dots.iter().rev() { - self.drawing.remove_fixed_dot(recorder, *dot); + self.drawing.recording(recorder).remove_fixed_dot(*dot); } return Err(err); @@ -132,7 +133,7 @@ impl Layout { recorder: &mut LayoutEdit, weight: FixedDotWeight, ) -> Result { - self.drawing.add_fixed_dot(recorder, weight) + self.drawing.recording(recorder).add_fixed_dot(weight) } pub fn add_fixed_dot_infringably( @@ -140,7 +141,9 @@ impl Layout { recorder: &mut LayoutEdit, weight: FixedDotWeight, ) -> FixedDotIndex { - self.drawing.add_fixed_dot_infringably(recorder, weight) + self.drawing + .recording(recorder) + .add_fixed_dot_infringably(weight) } pub fn add_poly_fixed_dot( @@ -149,10 +152,12 @@ impl Layout { weight: FixedDotWeight, poly: GenericIndex, ) -> Result { - let maybe_dot = self.drawing.add_fixed_dot(recorder, weight); + let maybe_dot = self.drawing.recording(recorder).add_fixed_dot(weight); if let Ok(dot) = maybe_dot { - self.drawing.add_to_compound(recorder, dot, poly.into()); + self.drawing + .recording(recorder) + .add_to_compound(dot, poly.into()); } maybe_dot @@ -164,8 +169,13 @@ impl Layout { weight: FixedDotWeight, poly: GenericIndex, ) -> FixedDotIndex { - let dot = self.drawing.add_fixed_dot_infringably(recorder, weight); - self.drawing.add_to_compound(recorder, dot, poly.into()); + let dot = self + .drawing + .recording(recorder) + .add_fixed_dot_infringably(weight); + self.drawing + .recording(recorder) + .add_to_compound(dot, poly.into()); dot } @@ -176,7 +186,9 @@ impl Layout { to: FixedDotIndex, weight: FixedSegWeight, ) -> Result { - self.drawing.add_fixed_seg(recorder, from, to, weight) + self.drawing + .recording(recorder) + .add_fixed_seg(from, to, weight) } pub fn add_fixed_seg_infringably( @@ -187,7 +199,8 @@ impl Layout { weight: FixedSegWeight, ) -> FixedSegIndex { self.drawing - .add_fixed_seg_infringably(recorder, from, to, weight) + .recording(recorder) + .add_fixed_seg_infringably(from, to, weight) } pub fn add_poly_fixed_seg( @@ -201,7 +214,9 @@ impl Layout { let maybe_seg = self.add_fixed_seg(recorder, from, to, weight); if let Ok(seg) = maybe_seg { - self.drawing.add_to_compound(recorder, seg, poly.into()); + self.drawing + .recording(recorder) + .add_to_compound(seg, poly.into()); } maybe_seg @@ -216,7 +231,9 @@ impl Layout { poly: GenericIndex, ) -> FixedSegIndex { let seg = self.add_fixed_seg_infringably(recorder, from, to, weight); - self.drawing.add_to_compound(recorder, seg, poly.into()); + self.drawing + .recording(recorder) + .add_to_compound(seg, poly.into()); seg } @@ -227,7 +244,9 @@ impl Layout { to: FixedDotIndex, weight: LoneLooseSegWeight, ) -> Result { - self.drawing.add_lone_loose_seg(recorder, from, to, weight) + self.drawing + .recording(recorder) + .add_lone_loose_seg(from, to, weight) } pub fn add_seq_loose_seg( @@ -237,7 +256,9 @@ impl Layout { to: LooseDotIndex, weight: SeqLooseSegWeight, ) -> Result { - self.drawing.add_seq_loose_seg(recorder, from, to, weight) + self.drawing + .recording(recorder) + .add_seq_loose_seg(from, to, weight) } pub fn move_dot( @@ -246,7 +267,7 @@ impl Layout { dot: DotIndex, to: Point, ) -> Result<(), Infringement> { - self.drawing.move_dot(recorder, dot, to) + self.drawing.recording(recorder).move_dot(dot, to) } pub fn add_poly( @@ -256,7 +277,8 @@ impl Layout { ) -> GenericIndex { GenericIndex::::new( self.drawing - .add_compound(recorder, CompoundWeight::Poly(weight)) + .recording(recorder) + .add_compound(CompoundWeight::Poly(weight)) .petgraph_index(), ) } @@ -266,7 +288,7 @@ impl Layout { recorder: &mut LayoutEdit, band: BandTermsegIndex, ) -> Result<(), DrawingException> { - self.drawing.remove_band(recorder, band) + self.drawing.recording(recorder).remove_band(band) } pub fn polys(