Cut an extrude's profiles that stand apart in one boolean (#848)
When an extrude cuts with profiles whose outlines stay more than 1 µm apart (the letters of a text), their tools are apart too, so they are joined and cut from the body in one boolean instead of one per profile. A ten-letter text cut drops from about 13 s to 1.5 s with the same result. Sheet metal targets and touching profiles keep cutting tool by tool. Tapered extrudes are unaffected.
This commit is contained in:
1 parent
96f6424aec
commit
1f7f37d1ef
6 files changed
+194
-3
No files matched your search
@@ -694,3 +694,38 @@ fn blind_bore_into_a_joined_boss_meshes() {
|
||||
let m = measure(&mut s);
|
||||
assert_eq!(m["bodies"].as_array().map(Vec::len), Some(1), "{m}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cutting_a_text_removes_each_letter_whether_its_letters_stand_apart_or_touch() {
|
||||
// Letters apart (cut at once by all of them), and two touching blocks (cut one after the other).
|
||||
for (text, touching) in [("SOLIDCRAFT", false), ("", true)] {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "sketch.create", json!({"plane":"XY"}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0":[0,0],"p1":[200,40]}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "solid.extrude", json!({"distance":10}));
|
||||
run(&mut s, "sketch.create", json!({"plane":"XY"}));
|
||||
if touching {
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0":[10,10],"p1":[20,20]}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0":[20,12],"p1":[30,18]}));
|
||||
} else {
|
||||
run(&mut s, "sketch.text", json!({"text":text,"at":[5,12],"height":14}));
|
||||
}
|
||||
let state = s.world_state();
|
||||
let ss = state.sketch(s.active_sketch.unwrap()).unwrap();
|
||||
// The profiles cut: the letters, not their counters (the inside of an O, whose outline
|
||||
// is a hole of its letter).
|
||||
let sorted = |ids: &[String]| {
|
||||
let mut ids = ids.to_vec();
|
||||
ids.sort();
|
||||
ids
|
||||
};
|
||||
let counter = |p: &solidcraft_sketch::Profile| ss.profiles.iter().any(|q| q.hole_curves.iter().any(|h| sorted(h) == sorted(&p.outer_curves)));
|
||||
let area: f64 = ss.profiles.iter().filter(|p| !counter(p)).map(|p| p.area).sum();
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "solid.extrude", json!({"distance":2,"operation":"cut"}));
|
||||
let volume = run(&mut s, "inspect.measure", json!({}))["total"]["volume_mm3"].as_f64().unwrap();
|
||||
assert!((volume - (200.0 * 40.0 * 10.0 - 2.0 * area)).abs() < 1e-3 * area, "{text:?}: {volume} for {area} mm² cut 2 mm deep");
|
||||
assert_eq!(s.world_state().bodies.len(), 1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user