Merge origin/main into fix/flush-pad-over-hole (keeps both round_pads_crossing_a_shallow_fall from #119 and drain_pads_flush_under_a_floor_with_a_hole, which now also checks a boss ring standing on the 1° top around the hole)

This commit is contained in:
CypherNaugh_0x committed 2026-10-11 15:01:29 +02:00
commit 49ca7ef878
28 files changed
+1333 -94

No files matched your search

+6 -3
View File
@@ -266,9 +266,12 @@ fn boolean_whole(a: &Body, b: &Body, op: BoolOp) -> Result<Option<Body>> {
let size = a.size().max(b.size());
// The checks mesh both bodies; where they meet in a region much thinner than they are (a
// thin part trimmed by a long one), a step from their size would facet the small faces
// there coarsely enough to fail the membership test on a correct result.
// there coarsely enough to fail the membership test on a correct result. The meshes are
// refined: a round side trimmed to a thin band (a short boss crossing a gently sloping
// floor) is otherwise spanned by triangles cutting through it, which reads as missing
// material.
let tol_m = (size * 5e-4).min(meeting_size(a, b) * 2e-3).max(size * 1e-5);
let meshes = (a.tessellate(tol_m).ok(), b.tessellate(tol_m).ok());
let meshes = (a.tessellate_with(tol_m, true).ok(), b.tessellate_with(tol_m, true).ok());
let (va, vb) = match &meshes {
(Some(ma), Some(mb)) => (ma.measure().volume, mb.measure().volume),
_ => (volume(a), volume(b)),
@@ -277,7 +280,7 @@ fn boolean_whole(a: &Body, b: &Body, op: BoolOp) -> Result<Option<Body>> {
// Volume bounds, then membership against the operands (catches misclassified pieces), on
// one mesh of the result. Returns (plausible, volume).
let check = |r: &Body| -> (bool, f64) {
let Ok(mr) = r.tessellate(tol_m) else { return (false, f64::NAN) };
let Ok(mr) = r.tessellate_with(tol_m, true) else { return (false, f64::NAN) };
let v = mr.measure().volume;
let bounds = v > 0.0
&& match op {