solidcraft-smlib: pin the fork at 2d7c7ed, the second round of SMLib C++ fixes

SMLIB_REV moves from 276b509 to capi-solidcraft 2d7c7ed: a fillet crash at an
unsupported corner (#453), rounds ending on a tangent seam (#418), radius laws
with a corner (#430) or that cannot be evaluated (#458), a round over a hole
(#422), a sphere's own patches kept apart (#423), offset surfaces extended the
same way whatever was evaluated first (#419), swept walls sharing their planes
(#434), the internal thread's last vertex gap (#410), shells across rounds
thinner than the wall (#397), nested shells imported in any order (#388) and
the tessellator held to its chord tolerance (#390).

Three tests follow: a radius law with a corner is now built, so the SMLib
tests check its volume (8000 - (1 - pi/4) 20 28/3) and that a law pinching to
zero inside the edge is refused; the split coil's halves now measure within
1e-5 of the closed form, so they are held to it rather than to the whole
coil's mesh, which is only within 3e-3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
This commit is contained in:
jyviko
2026-10-21 20:02:59 -04:00
parent e1a2571696
commit 1336352a43
4 changed files with 16 additions and 11 deletions
+3 -4
View File
@@ -451,10 +451,9 @@ mod tests {
fn options_smlib_cannot_build_are_refused() {
assert!(unsupported("x").to_string().contains("not supported yet"));
let b = cube();
// A radius law with a corner (4 → 2 → 4, straight on both halves).
let corner = RadiusSpline { degree: 1, knots: vec![0.0, 0.0, 0.5, 1.0, 1.0], radii: vec![4.0, 2.0, 4.0] };
let e = imp::variable(&b, Vec3::new(10.0, 20.0, 20.0), Vec3::new(0.0, 20.0, 20.0), &corner).unwrap_err();
assert!(e.to_string().contains("not supported yet"), "{e}");
// A radius law down to zero inside the edge would pinch the round to a point.
let pinch = RadiusSpline { degree: 1, knots: vec![0.0, 0.0, 0.5, 1.0, 1.0], radii: vec![4.0, 0.0, 4.0] };
assert!(imp::variable(&b, Vec3::new(10.0, 20.0, 20.0), Vec3::new(0.0, 20.0, 20.0), &pinch).is_err());
assert!(imp::blend(&b, "fillet", Kind::Round, &[Vec3::new(10.0, 20.0, 20.0)], &[f64::NAN]).is_err());
assert!(imp::blend(&b, "fillet", Kind::Round, &[Vec3::new(f64::NAN, 20.0, 20.0)], &[1.0]).is_err());
assert!(imp::blend(&b, "fillet", Kind::Round, &[], &[]).is_err());
+3 -1
View File
@@ -715,8 +715,10 @@ fn the_halves_of_a_split_smlib_coil_measure_as_the_whole() {
// π r² · 2πR · turns; SMLib's wall is a spline within a ten-thousandth of the pitch.
let (whole, analytic) = (volume(&coil), PI * 2.0 * PI * 20.0 * 6.0);
assert!((whole - analytic).abs() < 3e-3 * analytic, "coil {whole} vs {analytic}");
// The halves are held to the closed form itself: the whole coil's one wall is meshed
// within 3e-3 of it, which made the whole a looser yardstick than the truth.
let halves = volume(&upper) + volume(&lower);
assert!((halves - whole).abs() < 1e-3 * whole, "halves {halves} vs the whole {whole}");
assert!((halves - analytic).abs() < 1e-3 * analytic, "halves {halves} vs {analytic} (the whole measures {whole})");
}
/// Thinning keeps a grid within its cap whatever the rounding, both ends of each direction,
+1 -1
View File
@@ -1 +1 @@
276b509ad2b634843b2f256e1eb1fbaa29a5ef87
2d7c7edcff20b8f70c4e4d8aa952265bca2acc9d
+9 -5
View File
@@ -285,11 +285,15 @@ fn a_variable_round_follows_its_law() {
let zero = c.fillet_variable([10.0, 20.0, 20.0], 0.1, [0.0, 20.0, 20.0], 1, &knots, &[4.0, 0.0]).unwrap();
shot(&zero, "variable-to-zero");
assert_close(volume(&zero), 8000.0 - q * 20.0 * 16.0 / 3.0, 1e-5, "down to zero");
// A law with a corner (4 → 2 → 4, straight on both halves): SMLib's section fit runs across
// the corner and misses it, so it is refused; the same points joined smoothly (C1 cubic
// pieces, as RadiusSpline::through makes them) are built.
let corner = c.fillet_variable([10.0, 20.0, 20.0], 0.1, [0.0, 20.0, 20.0], 1, &[0.0, 0.0, 0.5, 1.0, 1.0], &[4.0, 2.0, 4.0]);
assert_eq!(corner.unwrap_err(), Error::Unsupported);
// A law with a corner (4 → 2 → 4, straight on both halves): the round turns at the corner,
// each half taking away (1 - pi/4) (L / 2) (16 + 8 + 4) / 3; the same points joined smoothly
// (C1 cubic pieces, as RadiusSpline::through makes them) are built too.
let corner = c.fillet_variable([10.0, 20.0, 20.0], 0.1, [0.0, 20.0, 20.0], 1, &[0.0, 0.0, 0.5, 1.0, 1.0], &[4.0, 2.0, 4.0]).unwrap();
shot(&corner, "variable-corner-4-2-4");
assert_close(volume(&corner), 8000.0 - q * 20.0 * 28.0 / 3.0, 1e-6, "corner law");
// A law down to zero inside the edge would pinch the round to a point: refused.
let pinch = c.fillet_variable([10.0, 20.0, 20.0], 0.1, [0.0, 20.0, 20.0], 1, &[0.0, 0.0, 0.5, 1.0, 1.0], &[4.0, 0.0, 4.0]);
assert!(pinch.is_err(), "a law pinching to zero inside the edge");
let smooth_knots = [0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0];
let smooth = c.fillet_variable([10.0, 20.0, 20.0], 0.1, [0.0, 20.0, 20.0], 3, &smooth_knots, &[4.0, 10.0 / 3.0, 2.0, 2.0, 2.0, 10.0 / 3.0, 4.0]);
shot(&smooth.unwrap(), "variable-smooth-4-2-4");