Kernel tests: a round as tall as its wall and more builds on the disc

The owner's blend-overflow ruling of 2026-10-30: a round that runs past
its face on its tangent side is built on the face continued and cut from
the part, keeping its radius. loop_fillet_as_tall_as_its_wall_consumes_it
still wanted R2.001 and R2.5 on the R13 x 2 disc refused as taller than the
wall; they now must build, valid, with the exact volume.

Proof. The round's section in (rho, z) is the r square at the top edge
outside the circle about (13 - r, 2 - r), clipped to z >= 0. With
t = z - (2 - r) = r sin(theta), the round's inner radius is
rho(theta) = 13 - r + r cos(theta), theta from asin((r - 2) / r) to pi/2,
and the disc keeps pi (169 * 2 - integral (169 - rho^2) dz), dz =
r cos(theta) dtheta (midpoint rule, 20000 steps). At r = 2 it is Pappus,
2 pi 169 - (1 - pi/4) 4 * 2 pi (13 - c), c = 2 (10 - 3 pi) / (3 (4 - pi))
(checked to 1e-9 in the test); at r = 2.5 it is 957.692239 mm3, the
ruling's number, the same integral as
rounds_past_the_bottom_of_a_wall_are_cut_from_the_part's. Graded at 1e-6
as that test is.

Today SMLib fails the R2.001 round (status 1001): a convex round past its
face is not yet built by subtraction, the cause fillets/KNOWN_FAILING gives
4782 and 5158.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-30 06:37:24 -04:00
committed by Irakli Kourtis
parent e9963439b1
commit 65e46a9628
+25 -3
View File
@@ -311,10 +311,32 @@ fn loop_fillet_as_tall_as_its_wall_consumes_it() {
let m = measure(&f).unwrap();
assert!(rel(m.volume, want) < 2e-4, "{} vs {want}", m.volume);
assert!(f.validity().is_empty(), "{:?}", f.validity());
// Taller than the wall: still refused, the body unchanged.
// Taller than the wall the round overflows on its tangent side, past the wall's bottom
// edge: it is built on the wall continued down and cut from the disc (the owner's
// blend-overflow ruling, 2026-10-30), keeping its radius. Its section in (ρ, z) is the r
// square at the edge outside the circle about (13 − r, 2 − r), above z = 0: with
// t = z − (2 − r) = r sin θ and ρ(θ) = 13 − r + r cos θ the disc keeps
// π (169·2 − ∫ (169 − ρ²) dz), θ from asin((r − 2) / r) (957.692239 at r = 2.5).
let kept = |r: f64| {
let (n, lo) = (20000, ((r - 2.0) / r).asin());
let taken: f64 = (0..n)
.map(|i| {
let th = lo + (f64::from(i) + 0.5) * (PI / 2.0 - lo) / f64::from(n);
let rho = 13.0 - r + r * th.cos();
(169.0 - rho * rho) * r * th.cos()
})
.sum::<f64>()
* (PI / 2.0 - lo)
/ f64::from(n);
PI * (169.0 * 2.0 - taken)
};
assert!(rel(kept(2.0), PI * 169.0 * 2.0 - spandrel(2.0).0 * 2.0 * PI * (13.0 - spandrel(2.0).1)) < 1e-9);
assert!((kept(2.5) - 957.692239).abs() < 1e-6, "{}", kept(2.5));
for r in [2.0 + 1e-3, 2.5] {
let e = fillet(&disc, &[Vec3::new(0.0, 13.0, 2.0), Vec3::new(0.0, -13.0, 2.0)], r).unwrap_err();
assert!(e.to_string().contains("taller than the walls"), "{r}: {e}");
let f = fillet(&disc, &[Vec3::new(0.0, 13.0, 2.0), Vec3::new(0.0, -13.0, 2.0)], r).unwrap_or_else(|e| panic!("{r}: {e}"));
assert!(f.validity().is_empty(), "{r}: {:?}", f.validity());
let v = measure(&f).unwrap().volume;
assert!(rel(v, kept(r)) < 1e-6, "{r}: {v} vs {}", kept(r));
}
}