mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 10:35:58 +00:00
Kernel tests: the collapsed taper's mesh is held to its B-rep, the taper to validity
collapsed_taper_mesh_stays_accurate_as_tolerance_decreases compared each display mesh's volume with the taper law's integral, 6000 - (1 - pi/4) 40 integral r^2, at 1e-4: the built fillet removes about 10 mm3 more than that (5212.9 against 5223.1) at every tolerance, so it measured the fillet, not the mesher. It now holds each mesh to the B-rep it meshes: a mesh within its chord tolerance of the faces has its volume within area x tolerance of the exact one (SMLib's, integrated on the surfaces to 1e-8), the bound fillet_mixed_arc_and_line_removed_volume _converges uses. It passes today. taper_follows_the_room_along_the_edge keeps its law and closed-form volumes (the 10 mm3 against the law is the failure it still shows) and drops the two internal checks at its end (no unmeshed face, a face with three vertices) for the outcome: the wedge's tapered fillet is valid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -730,8 +730,7 @@ mod tests {
|
||||
let f = fillet_variable_spline(&wedge, at, t.start, &t.spline).unwrap();
|
||||
let v = fine_volume(&f);
|
||||
assert!(rel(v, 6000.0 - removed(&law, 40.0)) < 1e-4, "{v} vs {}", 6000.0 - removed(&law, 40.0));
|
||||
assert_eq!(f.unmeshed_faces(), 0);
|
||||
assert!(faces_and_vertices(&f).0.contains(&3));
|
||||
assert!(f.validity().is_empty(), "{:?}", f.validity());
|
||||
}
|
||||
|
||||
/// A radius spline given directly: a cubic with its control radii pulling the radius up in
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
fn wedge() -> (Body, RadiusSpline) {
|
||||
fn wedge() -> Body {
|
||||
use solidcraft_geom::{Loop2, Plane, Region2, Vec2};
|
||||
let outer = Loop2::polygon(&[Vec2::new(0., 0.), Vec2::new(40., 0.), Vec2::new(0., 20.)]);
|
||||
let body = crate::extrude(&Plane::XY, &[Region2 { outer, holes: vec![] }], 0., 15.).unwrap().pop().unwrap();
|
||||
@@ -9,23 +9,22 @@ fn wedge() -> (Body, RadiusSpline) {
|
||||
// is built over the wedge's cliffs (the blend-overflow decision), so a tapered fillet no
|
||||
// longer tapers it.
|
||||
let t = taper(&body, at, 16.).unwrap();
|
||||
(fillet_variable_spline(&body, at, t.start, &t.spline).unwrap(), t.spline)
|
||||
}
|
||||
|
||||
fn expected(law: &RadiusSpline) -> f64 {
|
||||
let n = 20_000;
|
||||
let integral = (0..n).map(|i| law.eval((i as f64 + 0.5) / n as f64).powi(2)).sum::<f64>() / n as f64;
|
||||
6000. - (1. - std::f64::consts::FRAC_PI_4) * 40. * integral
|
||||
fillet_variable_spline(&body, at, t.start, &t.spline).unwrap()
|
||||
}
|
||||
|
||||
/// The display mesh of a fillet tapering to zero at a wedge's tip converges to the B-rep: each
|
||||
/// mesh lies within its chord tolerance of the faces, so its volume is within the body's area
|
||||
/// times that tolerance of the exact one (SMLib's, integrated on the surfaces, to 1e-8). Only
|
||||
/// the mesher is under test here; the taper's own law is `taper_follows_the_room_along_the_edge`'s.
|
||||
#[test]
|
||||
fn collapsed_taper_mesh_stays_accurate_as_tolerance_decreases() {
|
||||
let (body, law) = wedge();
|
||||
let wanted = expected(&law);
|
||||
let body = wedge();
|
||||
let exact = crate::measure(&body).unwrap();
|
||||
for tol in [0.002, 0.001, 0.0005, 0.0002] {
|
||||
let mesh = body.mesh(&crate::MeshTolerance::chord(tol)).unwrap();
|
||||
assert!(mesh.positions.iter().all(|p| p.x.is_finite() && p.y.is_finite() && p.z.is_finite()));
|
||||
let got = mesh.measure().volume;
|
||||
assert!((got - wanted).abs() / wanted < 1e-4, "tol={tol}: {got} vs {wanted}");
|
||||
let bound = exact.area * tol;
|
||||
assert!((got - exact.volume).abs() <= bound, "tol={tol}: mesh {got} vs exact {} (within {bound})", exact.volume);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user