diff --git a/crates/gpu/tests/capture.rs b/crates/gpu/tests/capture.rs index 4c618b2fc7..309c02e9d8 100644 --- a/crates/gpu/tests/capture.rs +++ b/crates/gpu/tests/capture.rs @@ -160,6 +160,8 @@ fn pictures_show_the_section_and_its_cap() { let mut cam = view::home_camera(&s).unwrap(); cam.fov = fov; let mut sc = view::scene(&s, &cam).unwrap(); + // The cap in the cap colour: a part's hatch colour is the one its name picks (#8529). + sc.part_hatch = None; // A marker inside the body, behind the cut face. let red = Rgb(255, 0, 0); sc.lines.push(SceneLine { diff --git a/crates/kernel/tests/chamfer_curved_holder.rs b/crates/kernel/tests/chamfer_curved_holder.rs index f45ab14a60..96196bb205 100644 --- a/crates/kernel/tests/chamfer_curved_holder.rs +++ b/crates/kernel/tests/chamfer_curved_holder.rs @@ -4,7 +4,7 @@ //! against the round wall instead of extending that short seam outside the solid. use solidcraft_geom::{Loop2, Plane, Region2, Seg2, Vec2, Vec3}; -use solidcraft_kernel::{Body, BoolOp, boolean, chamfer, cylinder, extrude}; +use solidcraft_kernel::{Body, BoolOp, boolean, chamfer, cylinder, extrude, tangent_chain}; use std::f64::consts::PI; fn holder() -> Body { @@ -54,7 +54,9 @@ fn expected_removed(distance: f64) -> f64 { #[test] fn chamfer_the_top_lip_at_a_tangent_wall_junction() { let body = holder(); - let made = chamfer(&body, &[Vec3::new(10.0, 10.0, 60.0)], 2.0).unwrap(); + // The pick's tangent chain, as a chamfer feature selects it (the kernel blends the edges it + // is given). + let made = chamfer(&body, &tangent_chain(&body, &[Vec3::new(10.0, 10.0, 60.0)]).unwrap(), 2.0).unwrap(); assert!(made.validity().is_empty(), "{:?}", made.validity()); assert_eq!(made.crossed_face_loops().unwrap(), 0); let history = made.history().expect("the chamfer retains exact face provenance"); @@ -115,7 +117,7 @@ fn plate_with_stadium(plate: f64) -> Body { fn one_chamfer_pick_follows_the_tangent_chain_at_any_part_size() { for plate in [140.0, 145.0, 250.0] { let body = plate_with_stadium(plate); - let made = chamfer(&body, &[Vec3::new(0.0, 5.0, 20.0)], 1.0).unwrap(); + let made = chamfer(&body, &tangent_chain(&body, &[Vec3::new(0.0, 5.0, 20.0)]).unwrap(), 1.0).unwrap(); assert!(made.validity().is_empty(), "{:?}", made.validity()); // Two straight edges (c^2/2 * 40 each) and both end arcs (Pappus, c^2/2 * 2 pi (R - c/3)). let expected = 40.0 + 0.5 * 2.0 * PI * (5.0 - 1.0 / 3.0); diff --git a/crates/smlib/src/export/tests.rs b/crates/smlib/src/export/tests.rs index 523d3a255f..daff933d4e 100644 --- a/crates/smlib/src/export/tests.rs +++ b/crates/smlib/src/export/tests.rs @@ -82,10 +82,19 @@ mod native_tests { fn edges_are_on_smlibs_curves() { let cyl = Brep::make_cylinder([0.0; 3], 5.0, 10.0).unwrap().to_native().unwrap(); let side = cyl.faces.iter().find(|f| matches!(f.surface, b::Surface::Cylinder { .. })).unwrap(); - assert!((side.domain[0][1] - side.domain[0][0] - TAU).abs() < 1e-12); - assert_eq!(side.domain[1], [0.0, 10.0]); + // The side is on SMLib's NURBS form of the cylinder (its domain is the form's): the whole + // turn, so its domain's two u ends meet, from the base to the top. + let form = b::eval::SurfaceEval::new(side.parameters()).unwrap(); + let [[u0, u1], [v0, v1]] = side.domain; + for v in [v0, v1] { + let (a, z) = (form.point([u0, v]).unwrap(), form.point([u1, v]).unwrap()); + assert!(a.dist(z) < 1e-9, "{a:?} {z:?}"); + } + let heights = [form.point([u0, v0]).unwrap().z, form.point([u0, v1]).unwrap().z]; + assert!(heights.iter().any(|h| h.abs() < 1e-9) && heights.iter().any(|h| (h - 10.0).abs() < 1e-9), "{heights:?}"); for e in &cyl.edges { - let eval = b::eval::CurveEval::new(&e.curve).unwrap(); + // Evaluated on the curve its interval is on (a circle's NURBS form). + let eval = b::eval::CurveEval::new(e.parameters()).unwrap(); let [a, z] = e.interval; // Ends on the edge's vertices. for (t, v) in [(a, e.vertices[0]), (z, e.vertices[1])] { @@ -94,6 +103,7 @@ mod native_tests { assert!((p - Vec3::new(q[0], q[1], q[2])).len() < 1e-9, "{:?} at {t}", e.curve); } if let b::Curve::Circle { radius, .. } = e.curve { + let [a, z] = e.curve_interval().unwrap(); assert!((radius - 5.0).abs() < 1e-12 && (z - a - TAU).abs() < 1e-9); } } @@ -126,7 +136,8 @@ mod native_tests { p[0].abs() < 1e-9 && (p[1] - 14.5).abs() < 1e-9 }) }; - let middle = |e: &b::Edge| b::eval::CurveEval::new(&e.curve).unwrap().point(0.5 * (e.interval[0] + e.interval[1])).unwrap(); + // On the curve the interval is on (a circle's NURBS form). + let middle = |e: &b::Edge| b::eval::CurveEval::new(e.parameters()).unwrap().point(0.5 * (e.interval[0] + e.interval[1])).unwrap(); let copies: Vec<&b::Edge> = record.edges.iter().filter(|e| on_line(e)).collect(); assert_eq!(copies.len(), 2); for copy in copies {