forked from 1b-agent/opencadstudio-upstream
bench: add COMMANDS suite with EXPLODE metrics
Shares the benchmark harness between both suites, extracts the plan/batch/apply helpers out of the EXPLODE command arm, and adds the command_benchmarks target.
This commit is contained in:
1 parent
c623a01695
commit
7978d1eb2e
7 files changed
+629
-321
No files matched your search
+7
-20
@@ -1202,40 +1202,27 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
"EXPLODE" => {
|
||||
use crate::modules::draw::modify::explode::explode_entity;
|
||||
let entities: Vec<_> = self.tabs[i]
|
||||
use crate::modules::draw::modify::explode::{
|
||||
apply_explode_replacements, plan_explode,
|
||||
};
|
||||
let selected: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.filter(|(handle, _)| !self.tabs[i].scene.is_layer_locked(*handle))
|
||||
.collect();
|
||||
if entities.is_empty() {
|
||||
if selected.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let cmd = SelectObjectsCommand::new("EXPLODE");
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
} else {
|
||||
let replacements: Vec<(codec::Handle, Vec<codec::EntityType>)> = entities
|
||||
.iter()
|
||||
.filter_map(|(h, e)| {
|
||||
let pieces = explode_entity(e, &self.tabs[i].scene.document);
|
||||
if pieces.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((*h, pieces))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let replacements = plan_explode(&selected, &self.tabs[i].scene.document);
|
||||
let exploded = replacements.len();
|
||||
if exploded > 0 {
|
||||
self.push_undo_snapshot(i, "EXPLODE");
|
||||
}
|
||||
for (handle, pieces) in replacements {
|
||||
self.tabs[i].scene.erase_entities(&[handle]);
|
||||
for piece in pieces {
|
||||
self.tabs[i].scene.add_entity(piece);
|
||||
}
|
||||
}
|
||||
apply_explode_replacements(&mut self.tabs[i].scene, replacements);
|
||||
if exploded > 0 {
|
||||
self.tabs[i].dirty = true;
|
||||
self.refresh_properties();
|
||||
|
||||
@@ -118,6 +118,52 @@ pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec<Entity
|
||||
}
|
||||
}
|
||||
|
||||
/// Explode every entity; one piece list per input, input order preserved,
|
||||
/// empty lists kept. Used by benchmarks and regression tests.
|
||||
pub fn explode_batch(
|
||||
items: &[(Handle, &EntityType)],
|
||||
doc: &CadDocument,
|
||||
) -> Vec<Vec<EntityType>> {
|
||||
items.iter().map(|(_, e)| explode_entity(e, doc)).collect()
|
||||
}
|
||||
|
||||
/// Plan the EXPLODE command for an already lock-filtered selection:
|
||||
/// order-preserving, empty pieces dropped (matching the command arm).
|
||||
pub fn plan_explode(
|
||||
selected: &[(Handle, &EntityType)],
|
||||
doc: &CadDocument,
|
||||
) -> Vec<(Handle, Vec<EntityType>)> {
|
||||
selected
|
||||
.iter()
|
||||
.filter_map(|(handle, entity)| {
|
||||
let pieces = explode_entity(entity, doc);
|
||||
if pieces.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((*handle, pieces))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Apply precomputed EXPLODE replacements. Initial version is a
|
||||
/// byte-for-byte extraction of the command arm's loop (erase one handle,
|
||||
/// add pieces one at a time); optimizations change its internals only.
|
||||
/// Returns the number of exploded sources.
|
||||
pub fn apply_explode_replacements(
|
||||
scene: &mut crate::scene::Scene,
|
||||
replacements: Vec<(Handle, Vec<EntityType>)>,
|
||||
) -> usize {
|
||||
let exploded = replacements.len();
|
||||
for (handle, pieces) in replacements {
|
||||
scene.erase_entities(&[handle]);
|
||||
for piece in pieces {
|
||||
scene.add_entity(piece);
|
||||
}
|
||||
}
|
||||
exploded
|
||||
}
|
||||
|
||||
fn explode_polyline(p: &Polyline) -> Vec<EntityType> {
|
||||
let n = p.vertices.len();
|
||||
if n < 2 {
|
||||
|
||||
Reference in new issue
Block a user