refactor(geometry/RecordingG...WithRtree): reduce code duplication and use HashMap Entry API

This commit is contained in:
Alain Emilia Anna Zscheile 2024-12-11 01:12:27 +01:00
parent 1879d74fac
commit 2f10462cb2
1 changed files with 110 additions and 175 deletions

View File

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