fix(kernel): fillet that uses up a side face makes a full round (#317)
A constant-radius fillet whose setback equals the width of a neighbouring
face was refused ("the blend is larger than the neighbouring faces"), so
r = 3 on the vertical edges of a 6 mm wide box failed while 2.999 worked.
The corner edge is now consumed: the rail ends at its far vertex and a side
face used up at both ends is removed, its remaining edge becoming the rail.
A face used up at one end only, and radii past the limit, are still refused.
Refs #199
Claude-Session: https://claude.ai/code/session_01TWc1smHYwTSVrVc8SNvS44
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a3ff816176
commit
a9e4830ded
3 files changed
+109
-17
No files matched your search
@@ -181,6 +181,39 @@ fn fillets_on_several_edges_and_angles() {
|
||||
assert!(fillet(&u, &[Vec3::new(15.0, 10.0, 20.0)], 1.0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fillet_consuming_a_side_face_makes_a_full_round() {
|
||||
// 14 x 6 x 10: r = 3 on the four vertical edges uses up both 6 mm end faces (#199).
|
||||
let b = box_solid(Vec3::new(14.0, 0.0, 0.0), Vec3::new(28.0, 6.0, 10.0)).unwrap();
|
||||
let mids = [Vec3::new(14.0, 0.0, 5.0), Vec3::new(28.0, 0.0, 5.0), Vec3::new(14.0, 6.0, 5.0), Vec3::new(28.0, 6.0, 5.0)];
|
||||
let full = 840.0 - (4.0 - PI) * 9.0 * 10.0;
|
||||
for order in [mids.to_vec(), mids.iter().rev().copied().collect()] {
|
||||
let f = fillet(&b, &order, 3.0).unwrap();
|
||||
let m = measure(&f).unwrap();
|
||||
assert!(rel(m.volume, full) < 2e-4, "{} vs {full}", m.volume);
|
||||
// Top, bottom, the two long sides and four quarter rounds; the end faces are gone.
|
||||
assert_eq!(m.faces, 8, "{m:?}");
|
||||
assert_eq!(f.lumps().unwrap().len(), 1);
|
||||
assert!(f.validity().is_empty(), "{:?}", f.validity());
|
||||
}
|
||||
// One end only: two rounds meeting on one end face.
|
||||
let f = fillet(&b, &mids[1..4].iter().step_by(2).copied().collect::<Vec<_>>(), 3.0).unwrap();
|
||||
assert!(rel(measure(&f).unwrap().volume, 840.0 - (4.0 - PI) * 9.0 * 5.0) < 2e-4);
|
||||
assert!(f.validity().is_empty());
|
||||
// A 6 x 6 post rounded on all four edges with r = 3 is a cylinder.
|
||||
let post = box_solid(Vec3::ZERO, Vec3::new(6.0, 6.0, 10.0)).unwrap();
|
||||
let corners = [Vec3::new(0.0, 0.0, 5.0), Vec3::new(6.0, 0.0, 5.0), Vec3::new(6.0, 6.0, 5.0), Vec3::new(0.0, 6.0, 5.0)];
|
||||
let c = fillet(&post, &corners, 3.0).unwrap();
|
||||
assert!(rel(measure(&c).unwrap().volume, PI * 9.0 * 10.0) < 2e-4, "{}", measure(&c).unwrap().volume);
|
||||
assert!(c.validity().is_empty());
|
||||
// Past the limit there is no face left to consume: still refused, the body unchanged.
|
||||
for r in [3.0 + 1e-3, 3.5] {
|
||||
let e = fillet(&b, &mids, r).unwrap_err();
|
||||
assert!(e.to_string().contains("larger than the neighbouring faces"), "{r}: {e}");
|
||||
}
|
||||
assert_eq!(measure(&b).unwrap().volume, 840.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tapered_extrudes() {
|
||||
// 40 x 40 square, 30 up, 10° outward: a frustum.
|
||||
|
||||
Reference in new issue
Block a user