Kernel tests: a circle is one closed arc, a round wall one face

Since 09c979a4b a full circle in a profile is one arc of a whole turn, so what is built from
it is one closed edge and one wall closed along its seam. Five kernel tests still expected
truck's halves:
- a_small_hole_in_a_large_spline_face_cuts_cleanly: the Ø1 hole adds one face (its wall),
  not two; the removed volume (π · 0.25 · 40) is unchanged.
- fit_loop (two mesh_convert tests): a fitted circle is Loop2::circle, one segment.
- tight_bend_counts: a Ø10 tube swept up 20, round a quarter turn of radius 5, along 20. The
  circle starts at (5, 0), which runs up to (5, 0, 20) on the bend's axis, where the turn
  leaves it: the bend face has no seam and both straights' seams end there. By the ladder's
  rule (each whole curve once, each seam): 5 faces (2 caps, one per path segment), 6 edges
  (4 circles, 2 seams), 3 vertices (the seams' ends: (5,0,0), (5,0,20), (25,0,20)), the
  record's own counts.
- extruded_circles_go_as_cylinders: the record holds the wall as the cylinder it is (one
  face of three), no longer a rational spline; it still goes into SMLib as its cylinder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-29 22:25:14 -04:00
committed by Irakli Kourtis
parent ec4eebaa82
commit 1bc8b204f1
4 changed files with 17 additions and 8 deletions
+3 -3
View File
@@ -34,9 +34,9 @@ fn intersection_curves(body: &Body) -> Vec<Curve> {
fn a_small_hole_in_a_large_spline_face_cuts_cleanly() {
let (block, cut) = holed();
assert!(cut.validity().is_empty(), "{:?}", cut.validity());
// The hole adds its wall (two half cylinders) and splits nothing: the bottom and the wave
// each gain a loop.
assert_eq!(cut.face_count(), block.face_count() + 2);
// The hole adds its wall (one cylinder, closed along its seam) and splits nothing: the
// bottom and the wave each gain a loop.
assert_eq!(cut.face_count(), block.face_count() + 1);
let curves = intersection_curves(&cut);
assert!(!curves.is_empty(), "the hole's rim on the wave is an intersection edge");
// The wave is within a few tenths of a millimetre of flat across a Ø1 hole, so the hole
+4 -2
View File
@@ -478,7 +478,8 @@ mod tests {
})
.collect();
assert_eq!(fit_loop(&points, 0.001, 1e-6).segs.len(), 16);
assert_eq!(fit_loop(&points, 0.2, 1e-6).segs.len(), 2);
// A circle is one closed arc.
assert_eq!(fit_loop(&points, 0.2, 1e-6).segs.len(), 1);
}
#[test]
@@ -549,7 +550,8 @@ mod tests {
.collect();
let inner = Loop2::polygon(&points);
let fitted = fit_loop(&points, 0.05, 1e-6);
assert_eq!(fitted.segs.len(), 2);
// Fitted as a circle: one closed arc.
assert_eq!(fitted.segs.len(), 1);
assert!(certify_nesting(&[outer.clone(), inner], &[outer, fitted], 1e-6, 3.).is_err());
}
@@ -62,13 +62,15 @@ fn smlib_results_go_back_into_smlib() {
}
/// Extruded circles go into SMLib as its cylinder, so a boolean with one intersects a plane with
/// a cylinder, not with a spline.
/// a cylinder, not with a spline. The record holds the wall as the cylinder it is (one face,
/// closed along its seam).
#[test]
fn extruded_circles_go_as_cylinders() {
use solidcraft_smlib::flat;
let body = cylinder(v(0., 50., -60.), v(0., 0., 1.), 40.0, 120.0).unwrap();
let record = super::brep_record(&body).unwrap();
assert!(record.faces.iter().any(|f| matches!(f.surface, solidcraft_geom::brep::Surface::RationalSpline { .. })));
let walls = record.faces.iter().filter(|f| matches!(f.surface, solidcraft_geom::brep::Surface::Cylinder { .. })).count();
assert_eq!((walls, record.faces.len()), (1, 3));
let arrays = solidcraft_smlib::import::arrays(&record, true).unwrap();
let kinds = &arrays.ints[&flat::FACE_SURFACE_TYPE];
assert!(kinds.iter().all(|k| *k == i64::from(flat::SURFACE_PLANE) || *k == i64::from(flat::SURFACE_CYLINDER)), "{kinds:?}");
+6 -1
View File
@@ -2327,7 +2327,11 @@ fn tight_bend_counts() {
];
let b = sweep(&Plane::XY, &region, &path).unwrap();
let m = measure(&b).unwrap().merged;
assert_eq!((m.faces, m.edges, m.vertices), (5, 6, 4), "{m:?}");
// Two caps and a face per path segment. The circle starts (one closed arc) at (5, 0), which
// runs up the first straight to (5, 0, 20) on the bend's axis: the turn leaves it there, so
// the bend has no seam, and the second straight's seam runs on from it to (25, 0, 20). Edges:
// the four circles and the two straights' seams; vertices: the seams' ends.
assert_eq!((m.faces, m.edges, m.vertices), (5, 6, 3), "{m:?}");
}
#[test]
@@ -2752,3 +2756,4 @@ fn a_box_cut_round_a_small_hole_of_a_long_plate_keeps_the_hole() {
}
}
}