Offsets picked faces along their normals into a new surface body: planes and cylinders move exactly, other faces get a fitted B-spline within tolerance, and offsets that would fold over are refused. Adds the SurfaceOffset feature (noted under format 18), the surface.offset engine command and an Offset Surface dialog. Closes #758. Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com>
This commit is contained in:
1 parent
15b5b51bf5
commit
2b70ed7b72
15 files changed
+574
-19
No files matched your search
@@ -939,6 +939,31 @@ fn surface_loft_dialog_makes_a_section_per_sketch() {
|
||||
assert_eq!(back.inputs[0].items, vec![Sel::SketchCurve { id: "a".into() }, Sel::SketchCurve { id: "b".into() }]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offset_surface_dialog_takes_faces_a_distance_and_the_chain() {
|
||||
// A box top picked, moved up 5: a 10 × 10 square at z = 15; Edit Feature brings it back.
|
||||
let mut app = app_with(json!([{"command": "solid.box", "params": {"length": 10, "width": 10, "height": 10, "body_name": "Box"}}]));
|
||||
let mut d = start(&mut app, vec![], "surface.offset");
|
||||
assert!(apply_commands(&app, &d).is_err(), "no faces yet");
|
||||
d.inputs[0].items = vec![Sel::Face { body: "Box".into(), index: 0, point: Vec3::new(5.0, 5.0, 10.0) }];
|
||||
if let Kind::Surface(crate::dialogs_surface::Surf::Offset { distance, chain }) = &mut d.kind {
|
||||
*distance = "5 mm".into();
|
||||
*chain = true;
|
||||
}
|
||||
let (id, p) = apply_commands(&app, &d).unwrap().remove(0);
|
||||
assert_eq!(
|
||||
(id.as_str(), &p["body"], &p["faces"], &p["chain"]),
|
||||
("surface.offset", &json!("Box"), &json!([[5.0, 5.0, 10.0]]), &json!(true)),
|
||||
"{p}"
|
||||
);
|
||||
app.session.execute(&id, &p).unwrap();
|
||||
let m = app.session.model.state().bodies.last().unwrap().mesh().measure();
|
||||
assert!((m.area - 100.0).abs() < 1e-6, "{}", m.area);
|
||||
let fid = app.session.doc.features.last().unwrap().id;
|
||||
let back = crate::dialogs::for_feature(&app, fid, None).unwrap();
|
||||
assert_eq!(back.inputs[0].items.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn patch_dialog_fills_a_loop_of_edges_that_is_not_planar() {
|
||||
// A box with its top cut away by a sideways cylinder: its rim is a closed loop of four
|
||||
|
||||
Reference in new issue
Block a user