One extrude cutting many circles from one sketch still cut the plate once per circle, each boolean rebuilding and re-meshing a plate grown by every hole before it (32 circles 2 s, 128 circles 60 s). The #261 fix joined clear tools with kernel::union_apart only in pattern replay; apply_traced now does it for every cut with 8 or more tools (patterns included), keeping each piece's face lineage.
This commit is contained in:
1 parent
6090e89b3f
commit
829912c6c5
2 files changed
+16
-11
No files matched your search
+16
-10
@@ -1132,6 +1132,21 @@ fn apply_op(state: &mut ModelState, f: &Feature, tools: Vec<Body>, op: Operation
|
||||
apply_traced(state, f, tools.into_iter().map(Traced::unnamed).collect(), op, targets)
|
||||
}
|
||||
|
||||
/// Many cut tools clear of each other (a pattern's copies, the circles of a vent field in one
|
||||
/// sketch) as one tool of many pieces, so the target is cut once instead of rebuilding an ever
|
||||
/// more complex body for every tool (#261, #368). Tools that may meet are left as they are.
|
||||
fn clear_tools_as_one(tools: Vec<Traced>) -> Vec<Traced> {
|
||||
if tools.len() < 8 {
|
||||
return tools;
|
||||
}
|
||||
let bodies: Vec<Body> = tools.iter().map(|t| t.body.clone()).collect();
|
||||
match kernel::union_apart(&bodies) {
|
||||
// Each piece's faces keep the names of the tool it is.
|
||||
Ok(Some(one)) => vec![Traced::step(one, &tools.iter().collect::<Vec<_>>())],
|
||||
_ => tools,
|
||||
}
|
||||
}
|
||||
|
||||
/// [`apply_op`] with tools whose lineage is known: the bodies it makes or changes keep theirs.
|
||||
fn apply_traced(state: &mut ModelState, f: &Feature, tools: Vec<Traced>, op: Operation, targets: &[String]) -> Result<()> {
|
||||
let tools = if op == Operation::Intersect { intersection_tool_union(tools)? } else { tools };
|
||||
@@ -1213,6 +1228,7 @@ fn apply_traced(state: &mut ModelState, f: &Feature, tools: Vec<Traced>, op: Ope
|
||||
}
|
||||
Operation::Cut | Operation::Intersect => {
|
||||
let bop = if op == Operation::Cut { BoolOp::Cut } else { BoolOp::Intersect };
|
||||
let tools = if op == Operation::Cut { clear_tools_as_one(tools) } else { tools };
|
||||
let affected: std::collections::BTreeSet<String> =
|
||||
target_idx.iter().filter_map(|i| state.bodies.get(*i).map(|b| b.name.clone())).collect();
|
||||
let mut remove = Vec::new();
|
||||
@@ -2798,16 +2814,6 @@ fn replay(
|
||||
}
|
||||
}
|
||||
}
|
||||
// Many cut copies clear of each other: one tool of many pieces, so the target is cut
|
||||
// once instead of rebuilding an ever more complex body for every copy (#261).
|
||||
if op == Operation::Cut && copies.len() >= 8 {
|
||||
let bodies: Vec<Body> = copies.iter().map(|t| t.body.clone()).collect();
|
||||
if let Ok(Some(one)) = kernel::union_apart(&bodies) {
|
||||
// Each piece's faces keep the names of the copy it is.
|
||||
let joined = Traced::step(one, &copies.iter().collect::<Vec<_>>());
|
||||
copies = vec![joined];
|
||||
}
|
||||
}
|
||||
// New bodies from a pattern join their source when they touch it (as one feature would).
|
||||
if f.body_names.is_empty() {
|
||||
apply_traced(st, f, copies, op, &targets)?;
|
||||
|
||||
@@ -285,7 +285,6 @@ fn sketch_hole_cut(n: usize) -> std::time::Duration {
|
||||
/// field: 32 took 2 s and 128 took 60 s, though a feature pattern of the same holes is near
|
||||
/// linear since #261. Linear is 4×. A ratio, not a time (see the 512-hole pattern test).
|
||||
#[test]
|
||||
#[ignore = "fails until #368 is fixed"]
|
||||
fn one_extrude_of_many_sketch_circles_scales_linearly() {
|
||||
let t32 = sketch_hole_cut(32);
|
||||
let t128 = sketch_hole_cut(128);
|
||||
|
||||
Reference in new issue
Block a user