mirror of https://codeberg.org/topola/topola.git
fix(geometry/recording_with_rtree): Do not inadvertedly invalidate bend bboxes
This fixes a crash that was happening when undoing autoroutings. Bends are still not restored correctly, I will fix that soon.
This commit is contained in:
parent
48fe63a387
commit
1f8ace9c77
|
|
@ -361,63 +361,6 @@ impl<
|
||||||
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
{
|
{
|
||||||
fn apply(&mut self, edit: &GeometryEdit<DW, SW, BW, CW, Cel, PI, DI, SI, BI>) {
|
fn apply(&mut self, edit: &GeometryEdit<DW, SW, BW, CW, Cel, PI, DI, SI, BI>) {
|
||||||
for (compound, (maybe_old_data, ..)) in &edit.compounds {
|
self.geometry_with_rtree.apply(edit);
|
||||||
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.clone());
|
|
||||||
|
|
||||||
for (entry_label, member) in members {
|
|
||||||
self.geometry_with_rtree.add_to_compound(
|
|
||||||
GenericIndex::<PW>::new(member.petgraph_index()),
|
|
||||||
*entry_label,
|
|
||||||
*compound,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ use crate::{
|
||||||
graph::{GenericIndex, GetPetgraphIndex},
|
graph::{GenericIndex, GetPetgraphIndex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::edit::{ApplyGeometryEdit, GeometryEdit};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Bbox {
|
pub struct Bbox {
|
||||||
pub aabb: AABB<[f64; 3]>,
|
pub aabb: AABB<[f64; 3]>,
|
||||||
|
|
@ -155,24 +157,6 @@ impl<
|
||||||
bend
|
bend
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_bend_at_index<W: AccessBendWeight + Into<PW> + GetLayer>(
|
|
||||||
&mut self,
|
|
||||||
bend: BI,
|
|
||||||
from: DI,
|
|
||||||
to: DI,
|
|
||||||
core: DI,
|
|
||||||
weight: W,
|
|
||||||
) {
|
|
||||||
self.geometry.add_bend_at_index(
|
|
||||||
GenericIndex::<W>::new(bend.petgraph_index()),
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
core,
|
|
||||||
weight,
|
|
||||||
);
|
|
||||||
self.init_bend_bbox(bend);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn add_compound_at_index(&mut self, compound: GenericIndex<CW>, weight: CW) {
|
pub(super) fn add_compound_at_index(&mut self, compound: GenericIndex<CW>, weight: CW) {
|
||||||
self.geometry
|
self.geometry
|
||||||
.add_compound_at_index(GenericIndex::<CW>::new(compound.petgraph_index()), weight);
|
.add_compound_at_index(GenericIndex::<CW>::new(compound.petgraph_index()), weight);
|
||||||
|
|
@ -491,3 +475,116 @@ impl<
|
||||||
self.geometry.compounds(node)
|
self.geometry.compounds(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
PW: GetWidth + GetLayer + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<Index = PI> + Copy,
|
||||||
|
DW: AccessDotWeight + Into<PW> + GetLayer,
|
||||||
|
SW: AccessSegWeight + Into<PW> + GetLayer,
|
||||||
|
BW: AccessBendWeight + Into<PW> + GetLayer,
|
||||||
|
CW: Clone,
|
||||||
|
Cel: Copy,
|
||||||
|
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Ord + Copy,
|
||||||
|
DI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||||
|
SI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||||
|
BI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||||
|
> ApplyGeometryEdit<DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
|
for GeometryWithRtree<PW, DW, SW, BW, CW, Cel, PI, DI, SI, BI>
|
||||||
|
{
|
||||||
|
fn apply(&mut self, edit: &GeometryEdit<DW, SW, BW, CW, Cel, PI, DI, SI, BI>) {
|
||||||
|
// First we remove every node that is in the edit. But we have to do
|
||||||
|
// this in a correct order, because otherwise some removals of some
|
||||||
|
// nodes may fail due to inadvertent invalidation of the bboxes of these
|
||||||
|
// nodes.
|
||||||
|
//
|
||||||
|
// We chose to first remove compounds, then bends and segs, and only
|
||||||
|
// then dots.
|
||||||
|
|
||||||
|
for (compound, (maybe_old_data, ..)) in &edit.compounds {
|
||||||
|
if maybe_old_data.is_some() {
|
||||||
|
self.remove_compound(*compound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because removal of a bend will invalidate bboxes of the bends wrapped
|
||||||
|
// around it, we first remove the bends from the R-tree, and their nodes
|
||||||
|
// from the graph only afterwards.
|
||||||
|
|
||||||
|
for (bend, (maybe_old_data, ..)) in &edit.bends {
|
||||||
|
if maybe_old_data.is_some() {
|
||||||
|
Self::rtree_remove_must_be_successful(
|
||||||
|
self.rtree.remove(&self.make_bend_bbox(*bend)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bend, (maybe_old_data, ..)) in &edit.bends {
|
||||||
|
if maybe_old_data.is_some() {
|
||||||
|
self.geometry.remove_primitive((*bend).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we add every node that is created or modified (but not removed)
|
||||||
|
// in the edit. This also has to be done in a right order, which we
|
||||||
|
// chose to be exactly the opposite of the order of the removal which we
|
||||||
|
// just did.
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just as with removal, we handle bend layout nodes and their bboxes
|
||||||
|
// separately to prevent failures from inadvertent bbox invalidation.
|
||||||
|
|
||||||
|
for (bend, (.., maybe_new_data)) in &edit.bends {
|
||||||
|
if let Some(((from, to, core), weight)) = maybe_new_data {
|
||||||
|
self.geometry.add_bend_at_index(
|
||||||
|
GenericIndex::<BW>::new(bend.petgraph_index()),
|
||||||
|
*from,
|
||||||
|
*to,
|
||||||
|
*core,
|
||||||
|
*weight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bend, (.., maybe_new_data)) in &edit.bends {
|
||||||
|
if let Some(..) = maybe_new_data {
|
||||||
|
self.init_bend_bbox(*bend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (compound, (.., maybe_new_data)) in &edit.compounds {
|
||||||
|
if let Some((members, weight)) = maybe_new_data {
|
||||||
|
self.add_compound_at_index(*compound, weight.clone());
|
||||||
|
|
||||||
|
for (entry_label, member) in members {
|
||||||
|
self.geometry.add_to_compound(
|
||||||
|
GenericIndex::<PW>::new(member.petgraph_index()),
|
||||||
|
*entry_label,
|
||||||
|
*compound,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue