fix(kernel): a small overlap is not taken for bodies apart or inside (#484)

When sample points say two bodies are apart or one is inside the other, the facetings are now checked for surfaces passing through each other; if they do, the boolean is computed instead of shortcut. If it still can't be intersected, the sampled answer is kept as a flagged, unverified result, and Interference lists such pairs as "could not be checked" with the reason. Fixes #442 and #443.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Scott BowdenandClaude Opus 5.5 authored and GitHub committed 2026-10-13 00:13:16 -04:00
1 parent 340ac0313a
commit 3159fc0dd0
8 files changed
+406 -25

No files matched your search

@@ -602,3 +602,26 @@ fn cylinder_auto_inference_refuses_ambiguity_curves_and_seam_crossing_atomically
assert_eq!(exact_cylinder_volume(&s), volume);
}
}
/// A cone that takes only a 1 mm chamfer off a cylinder's top edge leaves nearly all of the
/// cylinder inside it; the intersection is still the chamfered cylinder (#443).
#[test]
fn loft_intersect_that_trims_one_edge_changes_the_body() {
let mut s = Session::default();
run(&mut s, "sketch.create", json!({"plane": "XY"}));
run(&mut s, "sketch.circle.center", json!({"center": [0, 0], "radius": 35}));
run(&mut s, "sketch.finish", json!({}));
run(&mut s, "solid.extrude", json!({"distance": 10, "body_name": "Body"}));
for (name, offset, radius) in [("A", -1, 45), ("B", 11, 33)] {
run(&mut s, "sketch.create", json!({"plane": "XY", "offset": offset, "name": name}));
run(&mut s, "sketch.circle.center", json!({"center": [0, 0], "radius": radius}));
run(&mut s, "sketch.finish", json!({}));
}
run(&mut s, "solid.loft", json!({"sections": [{"sketch": "A"}, {"sketch": "B"}], "operation": "intersect"}));
// r 35 up to z = 9, then a frustum to r 34 at z = 10.
let want = std::f64::consts::PI * (35.0 * 35.0 * 9.0 + (35.0 * 35.0 + 35.0 * 34.0 + 34.0 * 34.0) / 3.0);
let got = volume(&mut s);
assert!((got - want).abs() < want * 2e-4, "{got} vs {want}");
let m = measure(&mut s);
assert_eq!(m["bodies"][0]["face_types"]["cone"], 1, "{m}");
}