mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 18:45:55 +00:00
step_in tests: the import's repair notes for added seams and turned faces
The schema 4 reader adds a seam to a face that winds around its surface without one
(3d7e465b1) and turns over a face whose loop disagrees with its same_sense, and notes
both (the spindle torus tests assert the seam note). The tests written against truck
expected no warnings:
- step_conformance_parts_read_back_their_exact_shape: each part's seam count (the cone,
dome, cylinder parts bounded by their rims alone); volumes, boxes, faces unchanged.
- extruded_ellipse_patch_crossing_profile_seam_stays_trimmed: same_sense .F. adds the
turned-over note.
- implicit_bound_can_still_describe_the_complement_of_a_patch becomes
implicit_bound_against_its_face_sense_turns_the_face_over: the strip's one bound on a
cylinder cannot be a hole (the cylinder is unbounded along its axis, so the face would
have no outer boundary); the loop bounds the face, turned over, the 42 mm2 strip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1850,11 +1850,17 @@ fn explicit_outer_bound_keeps_shallow_cylinder_patch_trimmed() {
|
||||
}
|
||||
}
|
||||
|
||||
/// The strip's one bound, not marked outer, on a face whose same_sense runs against it: the
|
||||
/// loop bounds the face and the face is turned over. Its complement is no face: the cylinder is
|
||||
/// unbounded along its axis, so the loop as a hole would leave a face with no outer boundary.
|
||||
#[test]
|
||||
fn implicit_bound_can_still_describe_the_complement_of_a_patch() {
|
||||
fn implicit_bound_against_its_face_sense_turns_the_face_over() {
|
||||
let imp = step_import(&shallow_cylinder_patch(false, false)).unwrap();
|
||||
let mesh = imp.bodies[0].body.mesh(&crate::MeshTolerance::chord(0.1)).unwrap();
|
||||
assert!(mesh.bounds().diagonal() > 5000.0, "without an explicit outer bound the loop is a hole");
|
||||
assert!(imp.warnings.iter().any(|w| w.contains("1 faces turned over: their loops disagree with their same_sense")), "{:?}", imp.warnings);
|
||||
let mesh = imp.bodies[0].body.mesh(&crate::MeshTolerance::chord(0.01)).unwrap();
|
||||
assert!(mesh.bounds().diagonal() < 10.0, "{:?}", mesh.bounds());
|
||||
assert!((mesh.measure().area - 42.0).abs() < 0.01, "area {}", mesh.measure().area);
|
||||
assert!(mesh.normals.iter().all(|n| n.x > 0.99), "the loop determines the face normal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1911,7 +1917,11 @@ fn extruded_ellipse_patch_crossing_profile_seam_stays_trimmed() {
|
||||
assert!(text.contains(&old));
|
||||
let text = text.replacen(&old, &surface, 1);
|
||||
let imported = step_import(&text).unwrap();
|
||||
assert_eq!(imported.warnings, ["solid 'Strip': imported as an open body (the shell is not closed)"]);
|
||||
// Against its loop (same_sense false) the face is turned over, and the import says so.
|
||||
let open = "solid 'Strip': imported as an open body (the shell is not closed)";
|
||||
let turned = "solid 'Strip': 1 faces turned over: their loops disagree with their same_sense";
|
||||
let want: &[&str] = if sense { &[open] } else { &[turned, open] };
|
||||
assert_eq!(imported.warnings, want, "sense={sense}, outer={outer}, radius={radius}");
|
||||
assert_eq!(imported.bodies.len(), 1);
|
||||
let body = &imported.bodies[0].body;
|
||||
assert_eq!(imported.bodies[0].file_faces, 1);
|
||||
@@ -1937,30 +1947,38 @@ fn extruded_ellipse_patch_crossing_profile_seam_stays_trimmed() {
|
||||
/// tessellation work) and the 1.4 MB `plate_900_holes`.
|
||||
#[test]
|
||||
fn step_conformance_parts_read_back_their_exact_shape() {
|
||||
// (file, exact volume (mm³), box (min, max), kernel faces, bodies)
|
||||
// (file, exact volume (mm³), box (min, max), kernel faces, bodies, seam edges the reader adds
|
||||
// to the items it reads: `cylinder_twice` places one item twice)
|
||||
#[rustfmt::skip]
|
||||
let parts: [(&str, &str, f64, [f64; 6], usize, usize); 17] = [
|
||||
("cone_point", include_str!("../../../../tests/step-conformance/cone_point.step"), 1000.0 * std::f64::consts::PI, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 2, 1),
|
||||
("cone_point_vertex", include_str!("../../../../tests/step-conformance/cone_point_vertex.step"), 1000.0 * std::f64::consts::PI, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 2, 1),
|
||||
("cylinder", include_str!("../../../../tests/step-conformance/cylinder.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1),
|
||||
("cylinder_inch", include_str!("../../../../tests/step-conformance/cylinder_inch.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1),
|
||||
("cylinder_nurbs", include_str!("../../../../tests/step-conformance/cylinder_nurbs.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1),
|
||||
("cylinder_placed", include_str!("../../../../tests/step-conformance/cylinder_placed.step"), 9424.778, [31.835, -33.165, 1.835, 65.485, 0.485, 35.485], 3, 1),
|
||||
("cylinder_seam", include_str!("../../../../tests/step-conformance/cylinder_seam.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1),
|
||||
("cylinder_twice", include_str!("../../../../tests/step-conformance/cylinder_twice.step"), 18849.556, [-10.0, -10.0, 0.0, 90.0, 10.0, 30.0], 6, 2),
|
||||
("dome", include_str!("../../../../tests/step-conformance/dome.step"), 16755.161, [-20.0, -20.0, 0.0, 20.0, 20.0, 20.0], 2, 1),
|
||||
("dome_nurbs", include_str!("../../../../tests/step-conformance/dome_nurbs.step"), 16755.161, [-20.0, -20.0, 0.0, 20.0, 20.0, 20.0], 2, 1),
|
||||
("far_cylinder", include_str!("../../../../tests/step-conformance/far_cylinder.step"), 9424.778, [99990.0, -10.0, 0.0, 100010.0, 10.0, 30.0], 3, 1),
|
||||
("grooved_shaft", include_str!("../../../../tests/step-conformance/grooved_shaft.step"), 153532.251, [-10.0, -10.0, 0.0, 10.0, 10.0, 501.0], 753, 1),
|
||||
("plate_100_holes", include_str!("../../../../tests/step-conformance/plate_100_holes.step"), 71588.321, [0.0, 0.0, 0.0, 100.0, 100.0, 10.0], 110, 1),
|
||||
("sheet_disc", include_str!("../../../../tests/step-conformance/sheet_disc.step"), 193396443.755, [-1800.0, -1800.0, 0.0, 1800.0, 1800.0, 19.0], 3, 1),
|
||||
("tiny_pin", include_str!("../../../../tests/step-conformance/tiny_pin.step"), std::f64::consts::FRAC_PI_8, [-0.25, -0.25, 0.0, 0.25, 0.25, 2.0], 3, 1),
|
||||
("torus_ring_nurbs", include_str!("../../../../tests/step-conformance/torus_ring_nurbs.step"), 4934.802, [-25.0, -25.0, 0.0, 25.0, 25.0, 5.0], 2, 1),
|
||||
("washer", include_str!("../../../../tests/step-conformance/washer.step"), 3534.292, [-20.0, -20.0, 0.0, 20.0, 20.0, 3.0], 4, 1),
|
||||
let parts: [(&str, &str, f64, [f64; 6], usize, usize, usize); 17] = [
|
||||
("cone_point", include_str!("../../../../tests/step-conformance/cone_point.step"), 1000.0 * std::f64::consts::PI, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 2, 1, 1),
|
||||
("cone_point_vertex", include_str!("../../../../tests/step-conformance/cone_point_vertex.step"), 1000.0 * std::f64::consts::PI, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 2, 1, 1),
|
||||
("cylinder", include_str!("../../../../tests/step-conformance/cylinder.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1, 1),
|
||||
("cylinder_inch", include_str!("../../../../tests/step-conformance/cylinder_inch.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1, 1),
|
||||
("cylinder_nurbs", include_str!("../../../../tests/step-conformance/cylinder_nurbs.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1, 1),
|
||||
("cylinder_placed", include_str!("../../../../tests/step-conformance/cylinder_placed.step"), 9424.778, [31.835, -33.165, 1.835, 65.485, 0.485, 35.485], 3, 1, 1),
|
||||
("cylinder_seam", include_str!("../../../../tests/step-conformance/cylinder_seam.step"), 9424.778, [-10.0, -10.0, 0.0, 10.0, 10.0, 30.0], 3, 1, 0),
|
||||
("cylinder_twice", include_str!("../../../../tests/step-conformance/cylinder_twice.step"), 18849.556, [-10.0, -10.0, 0.0, 90.0, 10.0, 30.0], 6, 2, 1),
|
||||
("dome", include_str!("../../../../tests/step-conformance/dome.step"), 16755.161, [-20.0, -20.0, 0.0, 20.0, 20.0, 20.0], 2, 1, 1),
|
||||
("dome_nurbs", include_str!("../../../../tests/step-conformance/dome_nurbs.step"), 16755.161, [-20.0, -20.0, 0.0, 20.0, 20.0, 20.0], 2, 1, 1),
|
||||
("far_cylinder", include_str!("../../../../tests/step-conformance/far_cylinder.step"), 9424.778, [99990.0, -10.0, 0.0, 100010.0, 10.0, 30.0], 3, 1, 1),
|
||||
("grooved_shaft", include_str!("../../../../tests/step-conformance/grooved_shaft.step"), 153532.251, [-10.0, -10.0, 0.0, 10.0, 10.0, 501.0], 753, 1, 0),
|
||||
("plate_100_holes", include_str!("../../../../tests/step-conformance/plate_100_holes.step"), 71588.321, [0.0, 0.0, 0.0, 100.0, 100.0, 10.0], 110, 1, 0),
|
||||
("sheet_disc", include_str!("../../../../tests/step-conformance/sheet_disc.step"), 193396443.755, [-1800.0, -1800.0, 0.0, 1800.0, 1800.0, 19.0], 3, 1, 1),
|
||||
("tiny_pin", include_str!("../../../../tests/step-conformance/tiny_pin.step"), std::f64::consts::FRAC_PI_8, [-0.25, -0.25, 0.0, 0.25, 0.25, 2.0], 3, 1, 1),
|
||||
("torus_ring_nurbs", include_str!("../../../../tests/step-conformance/torus_ring_nurbs.step"), 4934.802, [-25.0, -25.0, 0.0, 25.0, 25.0, 5.0], 2, 1, 1),
|
||||
("washer", include_str!("../../../../tests/step-conformance/washer.step"), 3534.292, [-20.0, -20.0, 0.0, 20.0, 20.0, 3.0], 4, 1, 2),
|
||||
];
|
||||
for (name, text, volume, bbox, faces, bodies) in parts {
|
||||
for (name, text, volume, bbox, faces, bodies, seams) in parts {
|
||||
let imp = step_import(text).unwrap_or_else(|e| panic!("{name}: {e}"));
|
||||
assert!(imp.warnings.is_empty(), "{name}: {:?}", imp.warnings);
|
||||
// A face that winds around its surface without a seam edge (a cone or a dome bounded by
|
||||
// its base circle alone, a cylinder by its two rims) gets one, and the import says so.
|
||||
let added: Option<usize> = imp
|
||||
.warnings
|
||||
.iter()
|
||||
.map(|w| w.strip_suffix(" seam edges added to faces that wind around their surface")?.rsplit(": ").next()?.parse::<usize>().ok())
|
||||
.sum();
|
||||
assert_eq!(added, Some(seams), "{name}: {:?}", imp.warnings);
|
||||
assert_eq!(imp.bodies.len(), bodies, "{name}");
|
||||
let (mut v, mut n) = (0.0, 0);
|
||||
let mut b = solidcraft_geom::Aabb3::EMPTY;
|
||||
|
||||
Reference in New Issue
Block a user