fix: report every fillet refusal of a radius too big as too large (#477)

`fit: reduce` acts only on refusals marked too large. Three kinds weren't:
the corner build's contact lines leaving their faces or running backwards,
and a curved chain's contact reaching past the end of the seam it trims. Two
more were hidden: a later edge's too-large refusal lost to an earlier edge's
other error, and the corner build's lost to the local blend's in `fillet`.
The messages are unchanged.

Refs #293

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Irakli KourtisandClaude Opus 5.5 authored and GitHub committed 2026-10-12 21:49:00 -04:00
1 parent ccc36dc1f9
commit aa156f4a9f
5 files changed
+65 -7

No files matched your search

+23
View File
@@ -356,6 +356,29 @@ fn fillet_max_finds_the_largest_radius_that_works() {
assert!(fillet_max(&b, &[Vec3::new(500.0, 0.0, 5.0)], 1.0).is_none());
}
/// A corner's rounds too large for its faces are refused as too large, so a fit can reduce
/// them, also where only the corner build finds it (the edge-by-edge blend failing otherwise).
#[test]
fn corner_rounds_larger_than_their_faces_are_too_large() {
let (l, eps) = (20.0, 1e-9);
let b = box_solid(Vec3::ZERO, Vec3::new(l, l, l)).unwrap();
let corner = [Vec3::new(10.0, 0.0, 0.0), Vec3::new(0.0, 10.0, 0.0), Vec3::new(0.0, 0.0, 10.0)];
// As wide as the faces: the first edge's round uses up its neighbour, then the edge-by-edge
// blend can't find it; the corner build is what says the radius is too large.
let e = fillet(&b, &corner, l).unwrap_err();
assert!(matches!(e, KernelError::TooLarge(_)), "{e}");
let (r, body) = fillet_max(&b, &corner, l).unwrap();
assert!((r - 19.99).abs() < eps, "{r}");
assert!(body.validity().is_empty(), "{:?}", body.validity());
// Three rounds along the edges past the corner cube, and the cube less its sphere octant.
let removed = 3.0 * (1.0 - PI / 4.0) * r * r * (l - r) + r * r * r * (1.0 - PI / 6.0);
assert!(rel(measure(&body).unwrap().volume, l * l * l - removed) < 2e-4);
// Different radii per edge, one wider than its faces.
let sel: Vec<(Vec3, f64)> = corner.iter().copied().zip([21.0, 5.0, 5.0]).collect();
let e = crate::blend_corner::fillet_radii(&b, &sel).unwrap_err();
assert!(matches!(e, KernelError::TooLarge(_)), "{e}");
}
#[test]
fn tapered_extrudes() {
// 40 x 40 square, 30 up, 10° outward: a frustum.