Surface Sweep: sheets carried from open curves and profiles along a path (#843)

Surface Sweep carries open curves and closed profile boundaries along a sketch path into surface bodies, with smooth walls along curved point paths. Adds the SurfaceSweep feature (format 18 note), the surface.sweep command, a dialog with Edit Feature support, and kernel and engine tests.

Part of #757.
This commit is contained in:
Irakli Kourtis authored and GitHub committed 2026-10-13 20:48:30 -04:00
1 parent 57d738eac4
commit aba57f1ca2
16 files changed
+480 -27

No files matched your search

+28
View File
@@ -882,6 +882,34 @@ fn surface_revolve_dialog_takes_curves_and_an_axis() {
assert_eq!(back.inputs[1].items, vec![Sel::Axis { name: "y".into() }]);
}
#[test]
fn surface_sweep_dialog_takes_curves_and_a_path() {
// A line along y carried 5 up a line in the XZ plane: a 10 × 5 sheet. Edit Feature brings
// back the curve and the path.
let mut app = app_with(json!([
{"command": "sketch.create", "params": {"plane": "XY"}},
{"command": "sketch.line", "params": {"points": [[0, 0], [0, 10]], "ids": ["l"]}},
{"command": "sketch.finish", "params": {}},
{"command": "sketch.create", "params": {"plane": "XZ"}},
{"command": "sketch.line", "params": {"points": [[0, 0], [0, 5]], "ids": ["up"]}},
{"command": "sketch.finish", "params": {}}
]));
let mut d = start(&mut app, vec![], "surface.sweep");
d.inputs[0].items = vec![Sel::SketchCurve { id: "l".into() }];
assert!(apply_commands(&app, &d).is_err(), "no path yet");
d.inputs[1].items = vec![Sel::SketchCurve { id: "up".into() }];
let (id, p) = apply_commands(&app, &d).unwrap().remove(0);
assert_eq!((id.as_str(), &p["path"], &p["curves"]), ("surface.sweep", &json!(["up"]), &json!(["l"])), "{p}");
assert_ne!(p["path_sketch"], p["sketch"], "{p}");
app.session.execute(&id, &p).unwrap();
let area = app.session.model.state().bodies.last().unwrap().mesh().measure().area;
assert!((area - 50.0).abs() < 1e-6, "{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, vec![Sel::SketchCurve { id: "l".into() }]);
assert_eq!(back.inputs[1].items, vec![Sel::SketchCurve { id: "up".into() }]);
}
#[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