diff --git a/src/geometry/recording_with_rtree.rs b/src/geometry/recording_with_rtree.rs index b950220..57a3530 100644 --- a/src/geometry/recording_with_rtree.rs +++ b/src/geometry/recording_with_rtree.rs @@ -1,3 +1,4 @@ +use std::collections::hash_map::Entry as HashMapEntry; use std::hash::Hash; use geo::Point; @@ -32,6 +33,12 @@ pub struct RecordingGeometryWithRtree< geometry_with_rtree: GeometryWithRtree, } +/// inherent associated types are unstable +/// see issue #8995 for more information +macro_rules! OurGeometryEdit { + () => { GeometryEdit } +} + impl< PW: GetWidth + GetLayer + TryInto + TryInto + TryInto + Retag + Copy, DW: AccessDotWeight + GetLayer, @@ -54,7 +61,7 @@ impl< pub fn add_dot + GetLayer>( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), weight: W, ) -> GenericIndex where @@ -75,7 +82,7 @@ impl< pub fn add_seg + GetLayer>( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), from: DI, to: DI, weight: W, @@ -101,7 +108,7 @@ impl< pub fn add_bend + GetLayer>( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), from: DI, to: DI, core: DI, @@ -128,7 +135,7 @@ impl< pub fn add_compound( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), weight: CW, ) -> GenericIndex { let compound = self.geometry_with_rtree.add_compound(weight); @@ -140,218 +147,124 @@ impl< pub fn add_to_compound( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), primitive: GenericIndex, compound: GenericIndex, ) { - let old_members = self - .geometry_with_rtree - .geometry() - .compound_members(compound) - .collect(); - let old_weight = self - .geometry_with_rtree - .geometry() - .compound_weight(compound); + let geometry = self.geometry_with_rtree.geometry(); + let old_members = geometry.compound_members(compound).collect(); + let old_weight = geometry.compound_weight(compound); - let new_members = self - .geometry_with_rtree - .geometry() - .compound_members(compound) - .collect(); - let new_weight = self - .geometry_with_rtree - .geometry() - .compound_weight(compound); + // TODO ??? - if let Some(value) = recorder.compounds.get_mut(&compound) { - value.1 = Some((new_members, new_weight)); - } else { - recorder.compounds.insert( - compound, - ( - Some((old_members, old_weight)), - Some((new_members, new_weight)), - ), - ); - } + let geometry = self.geometry_with_rtree.geometry(); + let new_members = geometry.compound_members(compound).collect(); + let new_weight = geometry.compound_weight(compound); + + 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, recorder: &mut OurGeometryEdit!(), dot: DI) -> Result<(), ()> { let weight = self.geometry_with_rtree.geometry().dot_weight(dot); self.geometry_with_rtree.remove_dot(dot)?; - - if let Some((None, Some(..))) = recorder.dots.get(&dot) { - recorder.dots.remove(&dot); - } else { - recorder.dots.insert(dot, (Some(weight), None)); - }; - + edit_remove_from_map(&mut recorder.dots, dot, weight); Ok(()) } - pub fn remove_seg( - &mut self, - recorder: &mut GeometryEdit, - seg: SI, - ) { - let weight = self.geometry_with_rtree.geometry().seg_weight(seg); - let joints = self.geometry_with_rtree.geometry().seg_joints(seg); + pub fn remove_seg(&mut self, recorder: &mut OurGeometryEdit!(), 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); - - if let Some((None, Some(..))) = recorder.segs.get(&seg) { - recorder.segs.remove(&seg); - } else { - recorder.segs.insert(seg, (Some((joints, weight)), None)); - } + edit_remove_from_map(&mut recorder.segs, seg, (joints, weight)); } - pub fn remove_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - ) { - let weight = self.geometry_with_rtree.geometry().bend_weight(bend); - let joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let core = self.geometry_with_rtree.geometry().core(bend); + pub fn remove_bend(&mut self, recorder: &mut OurGeometryEdit!(), 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); - - if let Some((None, Some(..))) = recorder.bends.get(&bend) { - recorder.bends.remove(&bend); - } else { - recorder - .bends - .insert(bend, (Some(((joints.0, joints.1, core), weight)), None)); - } + edit_remove_from_map( + &mut recorder.bends, + bend, + ((joints.0, joints.1, core), weight), + ); } pub fn remove_compound( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), compound: GenericIndex, ) { - let weight = self - .geometry_with_rtree - .geometry() - .compound_weight(compound); - let members = self - .geometry_with_rtree - .geometry() - .compound_members(compound) - .collect(); + 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); - - if let Some((None, Some(..))) = recorder.compounds.get(&compound) { - recorder.compounds.remove(&compound); - } else { - recorder - .compounds - .insert(compound, (Some((members, weight)), None)); - } + edit_remove_from_map(&mut recorder.compounds, compound, (members, weight)); } - pub fn move_dot( - &mut self, - recorder: &mut GeometryEdit, - dot: DI, - to: Point, - ) { + pub fn move_dot(&mut self, recorder: &mut OurGeometryEdit!(), 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); - if let Some(value) = recorder.dots.get_mut(&dot) { - value.1 = Some(new_weight); - } else { - recorder - .dots - .insert(dot, (Some(old_weight), Some(new_weight))); - } + recorder + .dots + .entry(dot) + .or_insert((Some(old_weight), None)) + .1 = Some(new_weight); } - pub fn shift_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - offset: f64, - ) { - let old_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let old_core = self.geometry_with_rtree.geometry().core(bend); - let old_weight = self.geometry_with_rtree.geometry().bend_weight(bend); - self.geometry_with_rtree.shift_bend(bend, offset); - let new_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let new_core = self.geometry_with_rtree.geometry().core(bend); - let new_weight = self.geometry_with_rtree.geometry().bend_weight(bend); + fn modify_bend(&mut self, recorder: &mut OurGeometryEdit!(), bend: BI, f: F) + where + F: FnOnce(&mut GeometryWithRtree, BI), + { + let geometry = self.geometry_with_rtree.geometry(); + let old_joints = geometry.bend_joints(bend); + let old_core = geometry.core(bend); + let old_weight = geometry.bend_weight(bend); - if let Some(value) = recorder.bends.get_mut(&bend) { - value.1 = Some(((new_joints.0, new_joints.1, new_core), new_weight)); - } else { - recorder.bends.insert( - bend, - ( - Some(((old_joints.0, old_joints.1, old_core), old_weight)), - Some(((new_joints.0, new_joints.1, new_core), new_weight)), - ), - ); - } + f(&mut self.geometry_with_rtree, bend); + + let geometry = self.geometry_with_rtree.geometry(); + let new_joints = geometry.bend_joints(bend); + let new_core = geometry.core(bend); + let new_weight = geometry.bend_weight(bend); + + recorder + .bends + .entry(bend) + .or_insert(( + Some(((old_joints.0, old_joints.1, old_core), old_weight)), + None, + )) + .1 = Some(((new_joints.0, new_joints.1, new_core), new_weight)); } - pub fn flip_bend( - &mut self, - recorder: &mut GeometryEdit, - bend: BI, - ) { - let old_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let old_core = self.geometry_with_rtree.geometry().core(bend); - let old_weight = self.geometry_with_rtree.geometry().bend_weight(bend); - self.geometry_with_rtree.flip_bend(bend); - let new_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let new_core = self.geometry_with_rtree.geometry().core(bend); - let new_weight = self.geometry_with_rtree.geometry().bend_weight(bend); + pub fn shift_bend(&mut self, recorder: &mut OurGeometryEdit!(), bend: BI, offset: f64) { + self.modify_bend(recorder, bend, |gwrtree, bend| { + gwrtree.shift_bend(bend, offset) + }); + } - if let Some(value) = recorder.bends.get_mut(&bend) { - value.1 = Some(((new_joints.0, new_joints.1, new_core), new_weight)); - } else { - recorder.bends.insert( - bend, - ( - Some(((old_joints.0, old_joints.1, old_core), old_weight)), - Some(((new_joints.0, new_joints.1, new_core), new_weight)), - ), - ); - } + pub fn flip_bend(&mut self, recorder: &mut OurGeometryEdit!(), bend: BI) { + self.modify_bend(recorder, bend, |gwrtree, bend| gwrtree.flip_bend(bend)); } pub fn reattach_bend( &mut self, - recorder: &mut GeometryEdit, + recorder: &mut OurGeometryEdit!(), bend: BI, maybe_new_inner: Option, ) { - let old_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let old_core = self.geometry_with_rtree.geometry().core(bend); - let old_weight = self.geometry_with_rtree.geometry().bend_weight(bend); - self.geometry_with_rtree - .reattach_bend(bend, maybe_new_inner); - let new_joints = self.geometry_with_rtree.geometry().bend_joints(bend); - let new_core = self.geometry_with_rtree.geometry().core(bend); - let new_weight = self.geometry_with_rtree.geometry().bend_weight(bend); - - if let Some(value) = recorder.bends.get_mut(&bend) { - value.1 = Some(((new_joints.0, new_joints.1, new_core), new_weight)); - } else { - recorder.bends.insert( - bend, - ( - Some(((old_joints.0, old_joints.1, old_core), old_weight)), - Some(((new_joints.0, new_joints.1, new_core), new_weight)), - ), - ); - } + self.modify_bend(recorder, bend, |gwrtree, bend| { + gwrtree.reattach_bend(bend, maybe_new_inner) + }); } pub fn compound_weight(&self, compound: GenericIndex) -> CW { @@ -382,6 +295,28 @@ impl< } } +fn edit_remove_from_map( + map: &mut std::collections::HashMap, Option)>, + index: I, + data: T, +) where + I: core::cmp::Eq + Hash, +{ + let to_be_inserted = (Some(data), None); + match map.entry(index) { + HashMapEntry::Occupied(mut occ) => { + if let (None, Some(_)) = occ.get() { + occ.remove(); + } else { + *occ.get_mut() = to_be_inserted; + } + } + HashMapEntry::Vacant(vac) => { + vac.insert(to_be_inserted); + } + } +} + impl< PW: GetWidth + GetLayer + TryInto + TryInto + TryInto + Retag + Copy, DW: AccessDotWeight + GetLayer, @@ -395,7 +330,7 @@ impl< > ApplyGeometryEdit for RecordingGeometryWithRtree { - fn apply(&mut self, edit: &GeometryEdit) { + fn apply(&mut self, edit: &OurGeometryEdit!()) { for (compound, (maybe_old_data, ..)) in &edit.compounds { if maybe_old_data.is_some() { self.geometry_with_rtree.remove_compound(*compound);