Tests: a round wall is one face, its name without a piece number

Since 09c979a4b a circle is one closed arc, so an extruded circle's wall, a hole's wall and a
cylinder's side are one face each, closed along a seam. Tests that counted truck's two halves:
- certified_annulus_side_rows_follow_radius_edits_and_clone and
  certified_side_transfer_preserves_geometry_and_unsupported_taper_refuses_atomically: the
  painted outer wall is 1 face (every vertex of it still at the painted radius), not 2;
- offset_surface_of_a_cylinder_and_a_box_top: the offset sleeve is 1 face (its area 2π·12·20
  unchanged);
- press_pull_then_curved_face_offsets_it: a click on the hole's wall offsets its 1 face;
- pi_case_faces_per_step_at_both_heights: each standoff (a ring, Ø6 round a Ø2.5 hole) adds 4
  faces, not 6: its outer and inner wall, its top, the floor inside its hole. So 23 after the
  first and 35 after the pattern of four; the port openings (3 × 4), the end cut-out (4) and the
  five vents (5 × 4) are planar and add what they did: 47, 51, 55, 71.
- the_round_sides_of_a_thin_ring_are_named_by_the_circle_they_run_beside: a thin ring 2 thick
  about the R10 circle has two walls, `F2:wall:c1:left` (radius 9: the counter-clockwise
  circle's left is inside) and `F2:wall:c1:right` (radius 11), with no numbers; each name is
  found again by a point on its own wall.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-29 22:55:46 -04:00
committed by Irakli Kourtis
parent add3ebdb03
commit bf74dcbbe8
3 changed files with 20 additions and 15 deletions
@@ -49,22 +49,22 @@ fn certified_annulus_side_rows_follow_radius_edits_and_clone() {
run(&mut s, "sketch.finish", json!({}));
run(&mut s, "solid.extrude", json!({"distance":10,"profiles":[{"point":[9.5,0]}],"body_name":"Ring"}));
paint(&mut s, "Ring", json!([10, 0, 5]));
assert_eq!(painted_radius(&s, "Ring", 10.), 2, "both constructed arc pieces share outer curve");
assert_eq!(painted_radius(&s, "Ring", 10.), 1, "the outer circle's wall is one face, closed along its seam");
let Column::FaceAppearance(target) = &s.doc.configs.columns[0] else { panic!() };
assert_eq!(target.certificate, Some(FaceCertificate::ExtrudeSide { sketch, curve: "outer".into() }));
run(&mut s, "parameters.change", json!({"name":dimensions[0],"expression":"12 mm"}));
run(&mut s, "parameters.change", json!({"name":dimensions[1],"expression":"9.25 mm"}));
run(&mut s, "config.activate", json!({"row":"Painted"}));
assert_eq!(painted_radius(&s, "Ring", 12.), 2);
assert_eq!(painted_radius(&s, "Ring", 12.), 1);
run(&mut s, "component.paste_new", json!({"component":part,"translate":[30,0,0]}));
assert_eq!(s.doc.configs.columns.len(), 2);
run(&mut s, "config.activate", json!({"row":"Painted"}));
assert_eq!(painted_radius(&s, "Ring (2)", 12.), 2);
assert_eq!(painted_radius(&s, "Ring (2)", 12.), 1);
let reopened = solidcraft_doc::Document::from_json(&s.doc.to_json()).unwrap();
let mut reopened = Session::new(reopened);
run(&mut reopened, "config.activate", json!({"row":"Painted"}));
assert_eq!(painted_radius(&reopened, "Ring", 12.), 2);
assert_eq!(painted_radius(&reopened, "Ring (2)", 12.), 2);
assert_eq!(painted_radius(&reopened, "Ring", 12.), 1);
assert_eq!(painted_radius(&reopened, "Ring (2)", 12.), 1);
run(&mut reopened, "config.activate", json!({"row":"Default"}));
assert!(reopened.doc.appearances.faces.is_empty());
}
@@ -227,11 +227,11 @@ fn certified_side_transfer_preserves_geometry_and_unsupported_taper_refuses_atom
run(&mut s, "occurrence.move", json!({"occurrence":occurrence,"translate":[30,20,0],"angle":90,"axis":[0,0,1],"capture":false}));
run(&mut s, "component.move_bodies", json!({"component":destination,"bodies":["Round"]}));
run(&mut s, "config.activate", json!({"row":"Painted"}));
assert_eq!(painted_radius(&s, "Round", 10.), 2);
assert_eq!(painted_radius(&s, "Round", 10.), 1);
let before = s.world_state().unwrap().body("Round").unwrap().mesh().bounds();
let mut s = Session::new(solidcraft_doc::Document::from_json(&s.doc.to_json()).unwrap());
run(&mut s, "config.activate", json!({"row":"Painted"}));
assert_eq!(painted_radius(&s, "Round", 10.), 2);
assert_eq!(painted_radius(&s, "Round", 10.), 1);
assert!(
s.world_state().unwrap().body("Round").unwrap().mesh().bounds().min.dist(before.min) < 1e-8,
"before {before:?}, reopened {:?}",
+4 -4
View File
@@ -1091,9 +1091,9 @@ mod tests {
}
}
/// Offset Surface: a cylinder's side picked once with its chain (both halves) moved out to
/// radius 12; a box top moved up exactly; a zero distance copies; past the axis refused, the
/// design left as it was; undo, redo and reopening.
/// Offset Surface: a cylinder's side (one face, closed along its seam) picked with its chain
/// moved out to radius 12; a box top moved up exactly; a zero distance copies; past the axis
/// refused, the design left as it was; undo, redo and reopening.
#[test]
fn offset_surface_of_a_cylinder_and_a_box_top() {
let mut s = Session::default();
@@ -1101,7 +1101,7 @@ mod tests {
run(&mut s, "surface.offset", json!({"faces": [[10, 0, 10]], "chain": true, "distance": 2, "body": "Can", "body_name": "Sleeve"}));
let st = s.world_state().unwrap();
let sleeve = &st.body("Sleeve").unwrap().body;
assert!(sleeve.is_surface() && sleeve.face_count() == 2);
assert!(sleeve.is_surface() && sleeve.face_count() == 1);
let want = 2.0 * std::f64::consts::PI * 12.0 * 20.0;
assert!((area(&s, "Sleeve") - want).abs() < want * 1e-3, "{} vs {want}", area(&s, "Sleeve")); // (measured on meshes)
assert!(st.body("Can").is_some(), "the source body stays");
+9 -4
View File
@@ -371,10 +371,15 @@ fn the_round_sides_of_a_thin_ring_are_named_by_the_circle_they_run_beside() {
run(&mut s, "solid.extrude", json!({"sketch": "Outline", "thin": true, "thickness": 2, "distance": 5, "name": "Ring"}));
let world = s.world_state().unwrap();
let names = solidcraft_doc::naming::face_names(world.bodies.first().unwrap());
// Each round side is two half cylinders, told apart by their numbers.
// Each round side is one cylinder, closed along its seam, so its name needs no number.
let walls: Vec<_> = names.iter().filter(|name| name.contains(":wall:")).collect();
assert_eq!(walls.len(), 4, "{names:?}");
for side in ["left", "right"] {
assert_eq!(walls.iter().filter(|name| name.contains(&format!(":wall:c1:{side}#"))).count(), 2, "{walls:?}");
assert_eq!(walls.len(), 2, "{names:?}");
// The wall is 2 thick about the circle (radius 9 to 11). The circle runs counter-clockwise,
// so its left is the inner side; each name is found again at a point on its own wall.
for (side, radius) in [("left", 9.0), ("right", 11.0)] {
let name = format!("F2:wall:c1:{side}");
assert!(walls.contains(&&name), "{walls:?}");
let at = solidcraft_geom::Vec3::new(0.0, radius, 2.5);
assert_eq!(solidcraft_doc::naming::face_names_at(&s.model.state(), &[at]), vec![name.clone()]);
}
}