A drain pad whose bore is the drain hole's wall (a ring joined flush under a floor, or overlapping it) now joins instead of failing with "coincident faces on curved bodies": the mesh intersection can't take two walls on one cylinder, and the coincident-face push only knew planes. Such unions now narrow one body's bore (its walls pushed toward the axis, clear of the other's), join, and cut the original bore's cylinder out again over that body's length, which is exact when the cylinder holds no material of either body (checked on samples). Inside that step a face is pushed into the other body only as deep as there is material behind it all over, so a narrowed rim over the other's bore can't fill it; then the other body's bore is narrowed instead. Test: drain_pads_flush_under_a_floor_with_a_hole (ring flush and 2 mm into a 1° floor, and a disc across the hole, against hand-calculated volumes)

This commit is contained in:
CypherNaugh_0x committed 2026-10-11 13:01:54 +02:00
1 parent a6bb8fc924
commit 8970254672
3 files changed
+230 -1

No files matched your search

+16
View File
@@ -175,6 +175,13 @@ thread_local! {
/// Set while a boolean runs on bodies whose coincident faces were pushed apart (no
/// second round of pushing).
static APART: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
/// Set while a union runs with a bore narrowed off a common cylinder (no second round).
static BORES: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}
/// Is a union with a narrowed bore running (see [`crate::coplanar::bore_union`])?
pub(crate) fn narrowing_bores() -> bool {
BORES.with(|c| c.get())
}
/// Boolean of two bodies. The result may be empty (`Ok(None)`) for a cut that removes
@@ -344,6 +351,15 @@ fn boolean_whole(a: &Body, b: &Body, op: BoolOp) -> Result<Option<Body>> {
}
}
}
// Bores on a common cylinder (a pad's bore around the hole it is joined over).
if op == BoolOp::Union && !BORES.with(|c| c.get()) && crate::coplanar::has_coincident_cylinders(a, b) {
BORES.with(|c| c.set(true));
let r = crate::coplanar::bore_union(a, b, &|body| check(body).0);
BORES.with(|c| c.set(false));
if let Some(body) = r {
return Ok(Some(body));
}
}
let mut empty_votes = 0;
let keep: Vec<Vec<Vec3>> = a.split_keep().iter().chain(b.split_keep()).cloned().collect();
for (attempt, j) in JITTER.iter().enumerate() {