Robustness tests: a round's tangent chain and the lid's closed-form volume

fillet_into_an_earlier_round picked the box's upright after rounding its top edge
and expected only that edge rounded. Since solid.fillet rounds each picked edge's
tangent chain by default (84bd2daad), the upright runs on through the first round's
end arc into the top right edge, and that is rounded too. The two-radius checks now
ask for exactly the picked edges (tangent_chain: false), and a new check rounds the
chain and expects what a round of the 38 mm top right edge takes off as well.

ribs_flush_with_a_window_change_nothing_away_from_them compared the lid with
6703.5222 mm³, the old kernel's chorded volume. The lid's closed form (the plate
with its rounded corners, the skirt, less the window, the slot and the notch) is
6703.5344 mm³, which SMLib gives; the test computes it, and the script's
description says it. Each rib's volume and area are checked to SMLib's mass
property accuracy (2e-7 relative) instead of 1e-6 absolute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-28 21:23:21 -04:00
committed by Irakli Kourtis
parent 5d25684a13
commit 52343ba23b
3 changed files with 27 additions and 8 deletions
+12 -3
View File
@@ -409,7 +409,14 @@ fn ribs_flush_with_a_window_change_nothing_away_from_them() {
s.run_script(&Value::Array(lid.to_vec())).unwrap();
let measure = |s: &Session| s.model.state().body("Lid").map(|b| solidcraft_kernel::measure(&b.body).unwrap()).unwrap();
let (v0, a0) = (measure(&s).volume, measure(&s).area);
assert!((v0 - 6703.5222).abs() < 1e-3, "{v0}");
// The plate with its rounded corners, the skirt, less the window, the slot and the notch
// through the skirt: (76.8 × 89.3 - (4 - π) × 9) × 2.4 + (71.5 × 84 - 68.5 × 81) × 3
// - 68 × 61 × 2.4 - 44 × 10 × 2.4 - 22 × 1.5 × 3.
let lid = (76.8 * 89.3 - (4.0 - std::f64::consts::PI) * 9.0) * 2.4 + (71.5 * 84.0 - 68.5 * 81.0) * 3.0
- 68.0 * 61.0 * 2.4
- 44.0 * 10.0 * 2.4
- 22.0 * 1.5 * 3.0;
assert!((v0 - lid).abs() < 1e-3, "{v0} vs {lid}");
for (i, rib) in ribs.iter().enumerate() {
let reply = s.execute(rib["command"].as_str().unwrap(), &rib["params"]).unwrap();
let id = reply["feature"].as_u64().unwrap();
@@ -418,13 +425,15 @@ fn ribs_flush_with_a_window_change_nothing_away_from_them() {
assert!(!result.warning.as_deref().unwrap_or_default().contains("tool displacement"), "{:?}", result.warning);
let m = measure(&s);
let n = (i + 1) as f64;
// The measure's accuracy: SMLib's mass properties come within 2e-7 of a closed form.
let (dv, da) = (2e-7 * m.volume, 2e-7 * m.area);
// 1.6 x 6 x 11.7 less the 1.35 x 6 x 3 inside the skirt.
assert!((m.volume - (v0 + n * 88.02)).abs() < 1e-6, "rib {}: {}", i + 1, m.volume - v0);
assert!((m.volume - (v0 + n * 88.02)).abs() < dv, "rib {}: {}", i + 1, m.volume - v0);
// Top 9.6, outer side 6 x 8.7 above the skirt, inner side 6 x 11.7 (flush with the
// window's side), ends 2 x (1.6 x 11.7 - 1.35 x 3); the skirt top 8.1, its inner side
// 18 and 1.5 of the plate go under the rib.
let area = 9.6 + 52.2 + 70.2 + 29.34 - 8.1 - 18.0 - 1.5;
assert!((m.area - (a0 + n * area)).abs() < 1e-6, "rib {}: area {} (no slit adds any)", i + 1, m.area - a0);
assert!((m.area - (a0 + n * area)).abs() < da, "rib {}: area {} (no slit adds any)", i + 1, m.area - a0);
}
let bounds = s.model.state().body("Lid").unwrap().body.mesh(&solidcraft_kernel::MeshTolerance::chord(0.01)).unwrap().bounds();
assert!((bounds.max.z - 14.1).abs() < 1e-9, "{}", bounds.max.z);
+14 -4
View File
@@ -272,21 +272,31 @@ fn shell_after_a_drilled_hole() {
/// Rounding a box's edges one at a time: an edge running into an earlier round (of the same
/// radius or another) takes off about what each round alone would (the corner where they meet
/// is small).
/// is small). The upright runs on tangentially into the first round's end arc, and that into
/// the top right edge: its tangent chain, which the default (`tangent_chain`) rounds too, taking
/// off about what a round of that edge (38 long, past the first round) would as well.
#[test]
fn fillet_into_an_earlier_round() {
let box_ = json!({"command": "solid.box", "params": {"length": 60, "width": 40, "height": 15}});
let lost = |r: f64, len: f64| (1.0 - PI / 4.0) * r * r * len;
for r2 in [2.0, 3.0] {
let s = script(json!([
box_,
{"command": "solid.fillet", "params": {"edges": [[30, 0, 15]], "radius": 2}},
{"command": "solid.fillet", "params": {"edges": [[60, 0, 7]], "radius": r2}}
{"command": "solid.fillet", "params": {"edges": [[30, 0, 15]], "radius": 2, "tangent_chain": false}},
{"command": "solid.fillet", "params": {"edges": [[60, 0, 7]], "radius": r2, "tangent_chain": false}}
]));
let lost = |r: f64, len: f64| (1.0 - PI / 4.0) * r * r * len;
let want = 36000.0 - lost(2.0, 60.0) - lost(r2, 15.0);
let v = total_volume(&s);
assert!((v - want).abs() < 2.0, "r2 {r2}: {v} vs {want}");
}
let s = script(json!([
box_,
{"command": "solid.fillet", "params": {"edges": [[30, 0, 15]], "radius": 2}},
{"command": "solid.fillet", "params": {"edges": [[60, 0, 7]], "radius": 2}}
]));
let want = 36000.0 - lost(2.0, 60.0) - lost(2.0, 15.0) - lost(2.0, 38.0);
let v = total_volume(&s);
assert!((v - want).abs() < 2.0, "the upright's tangent chain: {v} vs {want}");
}
/// Clean seeds (seed 16: a partial face contact, fused), and the original seed 5 edge contact,
@@ -1,5 +1,5 @@
{
"description": "A 76.8 x 89.3 x 2.4 lid plate (corner at x = 100) with its four vertical edges rounded 3 mm, a 1.5 mm skirt ring 3 mm high on it (outside 102.65..174.15 x 2.65..86.65), a 68 x 61 window and a 44 x 10 slot cut through, and a 22 x 6 notch in the skirt. Four 1.6 x 6 x 11.7 ribs are then joined standing on the plate (z = 2.4) over the skirt, each flush with a side of the window (x = 104.4 and x = 172.4). The joins needed retries that displaced the tool, and one left a zero-thickness slit through the skirt and plate at y = 25.5, far from any rib (#616). Each rib adds 1.6*6*11.7 - 1.35*6*3 = 88.02 mm3 and nothing changes away from it: 6703.5222 + 4 * 88.02 mm3.",
"description": "A 76.8 x 89.3 x 2.4 lid plate (corner at x = 100) with its four vertical edges rounded 3 mm, a 1.5 mm skirt ring 3 mm high on it (outside 102.65..174.15 x 2.65..86.65), a 68 x 61 window and a 44 x 10 slot cut through, and a 22 x 6 notch in the skirt. Four 1.6 x 6 x 11.7 ribs are then joined standing on the plate (z = 2.4) over the skirt, each flush with a side of the window (x = 104.4 and x = 172.4). The joins needed retries that displaced the tool, and one left a zero-thickness slit through the skirt and plate at y = 25.5, far from any rib (#616). Each rib adds 1.6*6*11.7 - 1.35*6*3 = 88.02 mm3 and nothing changes away from it: 6703.5344 + 4 * 88.02 mm3.",
"commands": [
{"command": "solid.box", "params": {"corner": [100, 0, 0], "length": 76.8, "width": 89.3, "height": 2.4, "body_name": "Lid"}},
{"command": "solid.fillet", "params": {"edges": [[100, 0, 1.2], [176.8, 0, 1.2], [100, 89.3, 1.2], [176.8, 89.3, 1.2]], "radius": 3}},