forked from 1b-agent/opencadstudio-upstream
perf(explode): batch erasure, section map, pre-sized vectors
EXPLODE apply 504ms -> 61ms (-88%), geometry 70.2ms -> 58.1ms (-17%) on the 2,500-compound fixture.
This commit is contained in:
1 parent
2fc7d15a36
commit
801882314f
2 files changed
+24
-23
No files matched your search
@@ -155,8 +155,9 @@ pub fn apply_explode_replacements(
|
||||
replacements: Vec<(Handle, Vec<EntityType>)>,
|
||||
) -> usize {
|
||||
let exploded = replacements.len();
|
||||
for (handle, pieces) in replacements {
|
||||
scene.erase_entities(&[handle]);
|
||||
let handles: Vec<Handle> = replacements.iter().map(|(h, _)| *h).collect();
|
||||
scene.erase_entities(&handles);
|
||||
for (_, pieces) in replacements {
|
||||
for piece in pieces {
|
||||
scene.add_entity(piece);
|
||||
}
|
||||
@@ -171,7 +172,7 @@ fn explode_polyline(p: &Polyline) -> Vec<EntityType> {
|
||||
}
|
||||
let closed = p.flags.is_closed();
|
||||
let n_segs = if closed { n } else { n - 1 };
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(n_segs);
|
||||
for i in 0..n_segs {
|
||||
let v0 = &p.vertices[i];
|
||||
let v1 = &p.vertices[(i + 1) % n];
|
||||
@@ -194,7 +195,7 @@ fn explode_polyline3d(p: &codec::entities::Polyline3D) -> Vec<EntityType> {
|
||||
}
|
||||
let closed = p.is_closed();
|
||||
let n_segs = if closed { n } else { n - 1 };
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(n_segs);
|
||||
for i in 0..n_segs {
|
||||
let v0 = &p.vertices[i];
|
||||
let v1 = &p.vertices[(i + 1) % n];
|
||||
@@ -224,7 +225,7 @@ fn explode_polyline2d(p: &Polyline2D) -> Vec<EntityType> {
|
||||
let normal = Vector3::new(normal.x, normal.y, normal.z);
|
||||
let plane = crate::entities::curve::ocs_plane(normal.clone(), elevation);
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(n_segs);
|
||||
for i in 0..n_segs {
|
||||
let v0 = &p.vertices[i];
|
||||
let v1 = &p.vertices[(i + 1) % n];
|
||||
@@ -303,7 +304,7 @@ fn explode_lwpolyline(p: &LwPolyline) -> Vec<EntityType> {
|
||||
let elevation = p.elevation;
|
||||
let n_segs = if p.is_closed { n } else { n - 1 };
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(n_segs);
|
||||
for i in 0..n_segs {
|
||||
let v0 = &p.vertices[i];
|
||||
let v1 = &p.vertices[(i + 1) % n];
|
||||
@@ -389,7 +390,7 @@ fn explode_mline(ml: &MLine) -> Vec<EntityType> {
|
||||
let closed = ml.flags.contains(codec::entities::MLineFlags::CLOSED);
|
||||
let scale = ml.scale_factor;
|
||||
let n_segs = if closed { n } else { n - 1 };
|
||||
let mut result = Vec::new();
|
||||
let mut result = Vec::with_capacity(n_segs * 3);
|
||||
|
||||
// Helper: build a Line from two Vector3 positions.
|
||||
let make_line = |common: &codec::entities::EntityCommon,
|
||||
|
||||
+16
-16
@@ -979,6 +979,18 @@ impl Scene {
|
||||
fn remove_entities(&mut self, handles: &[Handle], respect_layer_locks: bool) {
|
||||
let erase_handles = self.handles_expanded_for_leader_annotations(handles);
|
||||
|
||||
// One pass over document.objects instead of a scan per erased handle.
|
||||
let mut managers_by_section: HashMap<Handle, Vec<Handle>> = HashMap::default();
|
||||
for (handle, object) in self.document.objects.iter() {
|
||||
if let ObjectType::ClassObject(object) = object {
|
||||
if let codec::objects::ClassObjectData::SectionManager(manager) = &object.data {
|
||||
for §ion in &manager.sections {
|
||||
managers_by_section.entry(section).or_default().push(*handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut handle_set: HashSet<Handle> = HashSet::default();
|
||||
let mut erased: Vec<(Handle, ChangeKind)> = Vec::new();
|
||||
let mut selection_changed = false;
|
||||
@@ -996,22 +1008,10 @@ impl Scene {
|
||||
}) if !data.settings_handle.is_null() => Some(data.settings_handle),
|
||||
_ => None,
|
||||
});
|
||||
let section_managers: Vec<Handle> = self
|
||||
.document
|
||||
.objects
|
||||
.iter()
|
||||
.filter_map(|(handle, object)| match object {
|
||||
ObjectType::ClassObject(object) => match &object.data {
|
||||
codec::objects::ClassObjectData::SectionManager(manager)
|
||||
if manager.sections.contains(&h) =>
|
||||
{
|
||||
Some(*handle)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let section_managers: Vec<Handle> = managers_by_section
|
||||
.get(&h)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
// Delta-undo: capture the removed entity so an undo can re-insert it.
|
||||
if self.is_recording_undo() {
|
||||
let before = self.document.get_entity_arc(h);
|
||||
|
||||
Reference in new issue
Block a user