Lofts through three or more sections are smooth: each side is one B-spline surface through every section (the middle sections leave no edges); two sections stay ruled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 13:48:12 +00:00
1 parent 06186be555
commit 8045904c54
3 files changed
+100 -2

No files matched your search

+23
View File
@@ -1238,3 +1238,26 @@ fn shell_with_spherical_and_conical_faces() {
let v = measure(&s).unwrap().volume;
assert!(v > 0.1 * v0 && v < 0.6 * v0, "{v} of {v0}");
}
#[test]
fn smooth_loft_through_three_sections() {
// Squares 40 → 20 → 40 wide, 0, 20 and 40 up: the middle is pinched smoothly (no edge there).
let sq = |s: f64| Loop2::polygon(&[Vec2::new(-s, -s), Vec2::new(s, -s), Vec2::new(s, s), Vec2::new(-s, s)]);
let l = loft(&[(Plane::XY, sq(20.0)), (Plane::XY.offset(20.0), sq(10.0)), (Plane::XY.offset(40.0), sq(20.0))]).unwrap();
let m = measure(&l).unwrap();
// Smooth: between the ruled (two frustums, 2 · 20 · (1600 + 400 + 800)/3) and the box.
let ruled = 2.0 * 20.0 * (1600.0 + 400.0 + 800.0) / 3.0;
assert!(m.volume < ruled && m.volume > 40.0 * 400.0, "{}", m.volume);
// Four sides and two caps; the middle section leaves no edges.
assert_eq!(m.merged.faces, 6, "{:?}", m.merged);
assert_eq!(m.merged.edges, 12, "{:?}", m.merged);
// A circle, a square and a circle: valid and between the inner and outer bounds.
let c = loft(&[
(Plane::XY, Loop2::circle(Vec2::ZERO, 10.0)),
(Plane::XY.offset(15.0), sq(12.0)),
(Plane::XY.offset(30.0), Loop2::circle(Vec2::ZERO, 8.0)),
])
.unwrap();
let v = measure(&c).unwrap().volume;
assert!(v > PI * 64.0 * 30.0 && v < 576.0 * 30.0, "{v}");
}