A sweep along a path with sharp corners follows the corners: sweeping a rim profile along three lines (an open rectangle) gave a body of volume -0.0006 mm3 with its centre of mass at x = -3.5e9, and no error

kernel::sweep swept segment by segment: a line translates the profile along it, an arc turns it. At a sharp corner the next line runs within the plane the profile has reached, so the profile slid sideways in its own plane and the walls folded into an inside-out, zero-volume shell. Paths whose direction changes at a joint (more than 1e-3 rad) are now swept as a polyline by sweep_path, which mitres the corners; arcs become points within 0.01 mm. Smooth paths (lines and tangent arcs) are swept as before. Pipe uses the same path.

Tests: sweep_round_a_sharp_corner_is_mitred sweeps a 2 x 2 square along an L of two 10 mm lines and checks the volume, 80 mm3 (fails on main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CypherNaugh_0xandClaude Opus 5.5 authored and bherbruck committed 2026-10-10 17:57:34 -04:00
1 parent 3086c32a9a
commit 9a2a3cef8b
2 files changed
+72 -1

No files matched your search

+16
View File
@@ -258,6 +258,22 @@ fn loft_and_sweep() {
assert!(rel(measure(&t).unwrap().volume, expect) < 1e-3, "{} vs {expect}", measure(&t).unwrap().volume);
}
#[test]
fn sweep_round_a_sharp_corner_is_mitred() {
// A 2 × 2 square centred on an L of two 10 mm lines: lines alone would slide the profile
// along the second leg within its own plane (an empty, inside-out body). Mitred, the
// volume is the area times the path length.
let sq =
Region2 { outer: Loop2::polygon(&[Vec2::new(-1.0, -1.0), Vec2::new(1.0, -1.0), Vec2::new(1.0, 1.0), Vec2::new(-1.0, 1.0)]), holes: vec![] };
let path = [
PathSeg::Line { a: Vec3::ZERO, b: Vec3::new(0.0, 0.0, 10.0) },
PathSeg::Line { a: Vec3::new(0.0, 0.0, 10.0), b: Vec3::new(10.0, 0.0, 10.0) },
];
let b = sweep(&Plane::XY, &sq, &path).unwrap();
let m = measure(&b).unwrap();
assert!(rel(m.volume, 80.0) < 1e-9, "{}", m.volume);
}
#[test]
fn moving_a_body_with_an_intersection_curve_edge_ends() {
// A cylinder cut by a tilted box keeps an elliptical intersection curve as an edge. Moving