Command ids are SolveCraft's own: 173 ids that were another product's internal command ids become dotted, lower-case ids (<area>.<thing>[.<variant>]: solid.extrude, sketch.rectangle.two_point, sheet.flange, joint.drive, ...), in the registry, toolbar, dialogs, shortcuts, palette, control channel, MCP, examples, scenarios and docs
The old ids live only in crates/engine/src/legacy_ids.rs (the legacy migration table): find_command maps them, so old scripts, recipes and control calls keep working, and saved shortcuts, recent and pinned commands are migrated on load (designs store no command ids). Parity maps the observed catalog ids to ours through xtask/data/fusion-ids.tsv. The agent rule now reads: our own dotted id, never another product's. Cargo.toml's repository points at github.com/bherbruck/solvecraft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
740360d7c3
commit
d10312b7fd
158 files changed
+3611
-3205
No files matched your search
@@ -12,7 +12,7 @@ fn run(s: &mut Session, id: &str, p: Value) -> Value {
|
||||
}
|
||||
|
||||
fn volume(s: &mut Session) -> f64 {
|
||||
run(s, "MeasureCommand", json!({}))["total"]["volume_mm3"].as_f64().unwrap_or(f64::NAN)
|
||||
run(s, "inspect.measure", json!({}))["total"]["volume_mm3"].as_f64().unwrap_or(f64::NAN)
|
||||
}
|
||||
|
||||
fn rel(a: f64, b: f64) -> f64 {
|
||||
@@ -20,15 +20,15 @@ fn rel(a: f64, b: f64) -> f64 {
|
||||
}
|
||||
|
||||
fn flat(s: &mut Session) -> Value {
|
||||
run(s, "FusionSheetMetalFlatPatternCmd", json!({}))
|
||||
run(s, "sheet.flat_pattern", json!({}))
|
||||
}
|
||||
|
||||
/// A w x h base flange on XY.
|
||||
fn base(s: &mut Session, w: f64, h: f64) {
|
||||
run(s, "SketchCreate", json!({"plane": "XY", "name": "Base"}));
|
||||
run(s, "ShapeRectangleTwoPoint", json!({"p0": [0, 0], "p1": [w, h]}));
|
||||
run(s, "SketchStop", json!({}));
|
||||
run(s, "FusionSheetMetalFlangeCommand", json!({"sketch": "Base"}));
|
||||
run(s, "sketch.create", json!({"plane": "XY", "name": "Base"}));
|
||||
run(s, "sketch.rectangle.two_point", json!({"p0": [0, 0], "p1": [w, h]}));
|
||||
run(s, "sketch.finish", json!({}));
|
||||
run(s, "sheet.flange", json!({"sketch": "Base"}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -36,70 +36,70 @@ fn base_and_edge_flange_follow_the_k_factor() {
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
assert!(rel(volume(&mut s), 15000.0) < 1e-9);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
// Oracle 68: flat = 60 − 5 + (π/2)(2.5 + 0.44·2.5) + 20 − 5.
|
||||
let want = 60.0 - 5.0 + FRAC_PI_2 * (2.5 + 0.44 * 2.5) + 15.0;
|
||||
let f = flat(&mut s);
|
||||
assert!((f["flat_size_mm"][1].as_f64().unwrap_or(0.0) - want).abs() < 1e-6, "{f}");
|
||||
assert_eq!(f["bends"][0]["direction"], "up");
|
||||
assert!(rel(volume(&mut s), 18972.622) < 1e-4, "{}", volume(&mut s));
|
||||
let m = run(&mut s, "MeasureCommand", json!({}));
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
assert_eq!(m["total"]["faces"], 14, "{m}");
|
||||
// The angle is a parameter: 45° (oracle 70 uses height 15).
|
||||
let names = s.doc.features.last().map(|f| f.param_names.clone()).unwrap_or_default();
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": names[0], "expression": "15"}));
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": names[1], "expression": "45 deg"}));
|
||||
run(&mut s, "parameters.change", json!({"name": names[0], "expression": "15"}));
|
||||
run(&mut s, "parameters.change", json!({"name": names[1], "expression": "45 deg"}));
|
||||
assert!(rel(volume(&mut s), 18450.777) < 1e-4, "{}", volume(&mut s));
|
||||
assert!((flat(&mut s)["flat_size_mm"][1].as_f64().unwrap_or(0.0) - 73.685298).abs() < 1e-5);
|
||||
// DXF: outline and an up bend line.
|
||||
let d = run(&mut s, "sheet.export_dxf", json!({}));
|
||||
let text = d["dxf"].as_str().unwrap_or_default();
|
||||
assert!(text.contains("BEND_UP") && text.contains("OUTLINE"), "{text}");
|
||||
assert!(s.execute("FusionSheetMetalFlangeCommand", &json!({"edges": [[50, 30, 40]], "height": 20})).is_err(), "not on an edge");
|
||||
assert!(s.execute("sheet.flange", &json!({"edges": [[50, 30, 40]], "height": 20})).is_err(), "not on an edge");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rules_are_parameters() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": "Thick", "expression": "1.5 mm"}));
|
||||
run(&mut s, "FusionSheetMetalRulesCommand", json!({"name": "Custom", "thickness": "Thick", "k_factor": 0.33, "bend_radius": "3 mm"}));
|
||||
run(&mut s, "parameters.change", json!({"name": "Thick", "expression": "1.5 mm"}));
|
||||
run(&mut s, "sheet.manage_rules", json!({"name": "Custom", "thickness": "Thick", "k_factor": 0.33, "bend_radius": "3 mm"}));
|
||||
base(&mut s, 80.0, 50.0);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[40, 50, 1.5], [40, 0, 1.5]], "height": 20}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[40, 50, 1.5], [40, 0, 1.5]], "height": 20}));
|
||||
// Oracle 71: 50 − 9 + 2·(π/2)(3 + 0.495) + 2·15.5 = 82.980.
|
||||
let want = 50.0 - 2.0 * 4.5 + 2.0 * FRAC_PI_2 * (3.0 + 0.33 * 1.5) + 2.0 * 15.5;
|
||||
assert!((flat(&mut s)["flat_size_mm"][1].as_f64().unwrap_or(0.0) - want).abs() < 1e-6);
|
||||
assert!(rel(volume(&mut s), 10053.717) < 1e-4, "{}", volume(&mut s));
|
||||
// Thicker: everything follows.
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": "Thick", "expression": "2 mm"}));
|
||||
run(&mut s, "parameters.change", json!({"name": "Thick", "expression": "2 mm"}));
|
||||
let want = 50.0 - 2.0 * 5.0 + 2.0 * FRAC_PI_2 * (3.0 + 0.33 * 2.0) + 2.0 * 15.0;
|
||||
assert!((flat(&mut s)["flat_size_mm"][1].as_f64().unwrap_or(0.0) - want).abs() < 1e-6);
|
||||
let l = run(&mut s, "sheet.rules", json!({}));
|
||||
assert_eq!(l["active"], "Custom", "{l}");
|
||||
assert!(s.execute("FusionSheetMetalRulesCommand", &json!({"name": "Bad", "k_factor": 3})).is_err());
|
||||
assert!(s.execute("sheet.manage_rules", &json!({"name": "Bad", "k_factor": 3})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contour_flange_hem_and_tray() {
|
||||
// Oracle 72.
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "SketchCreate", json!({"plane": {"origin": [0, 0, 0], "x_dir": [1, 0, 0], "y_dir": [0, 0, -1]}, "name": "Contour"}));
|
||||
run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [40, 0], [40, -30], [70, -30]], "ids": ["l1", "l2", "l3"]}));
|
||||
run(&mut s, "SketchStop", json!({}));
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"sketch": "Contour", "curves": ["l1", "l2", "l3"], "distance": 50}));
|
||||
run(&mut s, "sketch.create", json!({"plane": {"origin": [0, 0, 0], "x_dir": [1, 0, 0], "y_dir": [0, 0, -1]}, "name": "Contour"}));
|
||||
run(&mut s, "sketch.line", json!({"points": [[0, 0], [40, 0], [40, -30], [70, -30]], "ids": ["l1", "l2", "l3"]}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "sheet.flange", json!({"sketch": "Contour", "curves": ["l1", "l2", "l3"], "distance": 50}));
|
||||
assert!(rel(volume(&mut s), 12097.622) < 1e-4, "{}", volume(&mut s));
|
||||
assert!((flat(&mut s)["flat_size_mm"][0].as_f64().unwrap_or(0.0) - 96.309734).abs() < 1e-5);
|
||||
// Oracle 73: flange, then a flat hem of 8.
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
run(&mut s, "FusionSheetMetalHemFlangeCommand", json!({"edges": [[50, 0, 20]], "length": 8}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
run(&mut s, "sheet.hem", json!({"edges": [[50, 0, 20]], "length": 8}));
|
||||
assert!(rel(volume(&mut s), 21334.723) < 1e-4, "{}", volume(&mut s));
|
||||
let b = flat(&mut s)["bends"].clone();
|
||||
assert!(b.as_array().is_some_and(|a| a.iter().any(|x| (x["angle_deg"].as_f64().unwrap_or(0.0) - 180.0).abs() < 1e-9)), "{b}");
|
||||
// A tray: four flanges at once stop at each other's bends.
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[50, 60, 2.5], [100, 30, 2.5], [50, 0, 2.5], [0, 30, 2.5]], "height": 25}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[50, 60, 2.5], [100, 30, 2.5], [50, 0, 2.5], [0, 30, 2.5]], "height": 25}));
|
||||
let f = flat(&mut s);
|
||||
// Oracle 69: 100 − 10 + 2·5.655 + 2·20 = 141.310 across.
|
||||
assert!((f["flat_size_mm"][0].as_f64().unwrap_or(0.0) - (90.0 + 2.0 * FRAC_PI_2 * 3.6 + 40.0)).abs() < 1e-6, "{f}");
|
||||
@@ -117,15 +117,15 @@ fn unfold_cut_refold_and_convert() {
|
||||
// Oracle 74: two flanges, unfold, a slot across the bend, refold.
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 80.0, 50.0);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[40, 50, 2.5], [40, 0, 2.5]], "height": 20}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[40, 50, 2.5], [40, 0, 2.5]], "height": 20}));
|
||||
let folded = volume(&mut s);
|
||||
run(&mut s, "FusionSheetmetalUnfoldCommand", json!({}));
|
||||
let m = run(&mut s, "MeasureCommand", json!({}));
|
||||
run(&mut s, "sheet.unfold", json!({}));
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
assert!((m["bodies"][0]["bbox"]["max"][2].as_f64().unwrap_or(0.0) - 2.5).abs() < 1e-6, "{m}");
|
||||
run(&mut s, "SketchCreate", json!({"plane": "XY", "name": "Slot"}));
|
||||
run(&mut s, "ShapeRectangleTwoPoint", json!({"p0": [35, -12], "p1": [45, 10]}));
|
||||
run(&mut s, "SketchStop", json!({}));
|
||||
run(&mut s, "Extrude", json!({"sketch": "Slot", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY", "name": "Slot"}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0": [35, -12], "p1": [45, 10]}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "solid.extrude", json!({"sketch": "Slot", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
run(&mut s, "sheet.refold", json!({}));
|
||||
let v = volume(&mut s);
|
||||
assert!(v < folded - 300.0, "{v} {folded}");
|
||||
@@ -133,24 +133,24 @@ fn unfold_cut_refold_and_convert() {
|
||||
assert_eq!(flat(&mut s)["cutouts"].as_array().map(Vec::len), Some(1));
|
||||
// Convert a plate.
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "PrimitiveBox", json!({"length": 100, "width": 60, "height": 2.5, "body_name": "Plate"}));
|
||||
run(&mut s, "ConvertToSheetMetalCmd", json!({"body": "Plate", "face": [50, 30, 2.5]}));
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
run(&mut s, "solid.box", json!({"length": 100, "width": 60, "height": 2.5, "body_name": "Plate"}));
|
||||
run(&mut s, "sheet.convert", json!({"body": "Plate", "face": [50, 30, 2.5]}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[50, 0, 2.5]], "height": 20}));
|
||||
assert!(rel(volume(&mut s), 18972.622) < 1e-4, "{}", volume(&mut s));
|
||||
let mut t = Session::default();
|
||||
run(&mut t, "PrimitiveCylinder", json!({"radius": 10, "height": 30, "body_name": "Rod"}));
|
||||
assert!(t.execute("ConvertToSheetMetalCmd", &json!({"body": "Rod", "face": [0, 0, 30]})).is_err());
|
||||
run(&mut t, "solid.cylinder", json!({"radius": 10, "height": 30, "body_name": "Rod"}));
|
||||
assert!(t.execute("sheet.convert", &json!({"body": "Rod", "face": [0, 0, 30]})).is_err());
|
||||
}
|
||||
|
||||
/// A sketch line across a 100 x 60 plate's top face at x = 40.
|
||||
fn fold_line(s: &mut Session) {
|
||||
run(s, "SketchCreate", json!({"plane": "XY", "offset": 2.5, "name": "FoldLine"}));
|
||||
run(s, "DrawPolyline", json!({"points": [[40, 0], [40, 60]], "ids": ["fl"]}));
|
||||
run(s, "SketchStop", json!({}));
|
||||
run(s, "sketch.create", json!({"plane": "XY", "offset": 2.5, "name": "FoldLine"}));
|
||||
run(s, "sketch.line", json!({"points": [[40, 0], [40, 60]], "ids": ["fl"]}));
|
||||
run(s, "sketch.finish", json!({}));
|
||||
}
|
||||
|
||||
fn bbox(s: &mut Session) -> Value {
|
||||
run(s, "MeasureCommand", json!({}))["bodies"][0]["bbox"].clone()
|
||||
run(s, "inspect.measure", json!({}))["bodies"][0]["bbox"].clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -160,7 +160,7 @@ fn fold_takes_the_bend_out_of_the_flat_sheet() {
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
fold_line(&mut s);
|
||||
run(&mut s, "SheetMetalFoldCmd", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
run(&mut s, "sheet.fold", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
// The flat pattern keeps its size; the bend's centre line is the sketch line.
|
||||
let f = flat(&mut s);
|
||||
assert!((f["flat_size_mm"][0].as_f64().unwrap_or(0.0) - 100.0).abs() < 1e-6, "{f}");
|
||||
@@ -189,7 +189,7 @@ fn fold_positions_fixed_side_and_flip() {
|
||||
for (k, v) in p.as_object().into_iter().flatten() {
|
||||
q[k] = v.clone();
|
||||
}
|
||||
run(&mut s, "SheetMetalFoldCmd", q);
|
||||
run(&mut s, "sheet.fold", q);
|
||||
bbox(&mut s)
|
||||
};
|
||||
let x0 = |b: &Value| b["min"][0].as_f64().unwrap_or(f64::NAN);
|
||||
@@ -215,10 +215,10 @@ fn fold_carries_flanges_on_the_moving_side() {
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
// A flange on the left edge, then a fold between it and the rest.
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[0, 30, 2.5]], "height": 20}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[0, 30, 2.5]], "height": 20}));
|
||||
let v0 = volume(&mut s);
|
||||
fold_line(&mut s);
|
||||
run(&mut s, "SheetMetalFoldCmd", json!({"sketch": "FoldLine", "curve": "fl", "fixed": [90, 30, 2.5]}));
|
||||
run(&mut s, "sheet.fold", json!({"sketch": "FoldLine", "curve": "fl", "fixed": [90, 30, 2.5]}));
|
||||
// The flange rode along: it is above the plate now, nothing left at z < 0.
|
||||
let b = bbox(&mut s);
|
||||
assert!(b["min"][2].as_f64().unwrap_or(-1.0) > -1e-6, "{b}");
|
||||
@@ -229,9 +229,9 @@ fn fold_carries_flanges_on_the_moving_side() {
|
||||
// Errors: off the sheet, through the flange's bend.
|
||||
let mut e = Session::default();
|
||||
base(&mut e, 100.0, 60.0);
|
||||
assert!(e.execute("SheetMetalFoldCmd", &json!({"points": [[40, 0, 30], [40, 60, 30]]})).is_err());
|
||||
assert!(e.execute("SheetMetalFoldCmd", &json!({"points": [[40, 0, 2.5], [40, 60, 2.5]], "position": "sideways"})).is_err());
|
||||
assert!(e.execute("SheetMetalFoldCmd", &json!({"points": [[0.5, 0, 2.5], [0.5, 60, 2.5]]})).is_err(), "no material past the bend");
|
||||
assert!(e.execute("sheet.fold", &json!({"points": [[40, 0, 30], [40, 60, 30]]})).is_err());
|
||||
assert!(e.execute("sheet.fold", &json!({"points": [[40, 0, 2.5], [40, 60, 2.5]], "position": "sideways"})).is_err());
|
||||
assert!(e.execute("sheet.fold", &json!({"points": [[0.5, 0, 2.5], [0.5, 60, 2.5]]})).is_err(), "no material past the bend");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -240,12 +240,12 @@ fn fold_on_a_flange_panel() {
|
||||
let ba = FRAC_PI_2 * (r + k * t);
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[50, 0, 2.5]], "height": 30}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[50, 0, 2.5]], "height": 30}));
|
||||
let flat0 = flat(&mut s)["flat_size_mm"].clone();
|
||||
let v0 = volume(&mut s);
|
||||
// The flange stands up at the plate's y = 0 edge: its outer face is the body's min y.
|
||||
let y = bbox(&mut s)["min"][1].as_f64().unwrap_or(f64::NAN);
|
||||
run(&mut s, "SheetMetalFoldCmd", json!({"points": [[10, y, 18], [90, y, 18]]}));
|
||||
run(&mut s, "sheet.fold", json!({"points": [[10, y, 18], [90, y, 18]]}));
|
||||
let f = flat(&mut s);
|
||||
for i in 0..2 {
|
||||
assert!(
|
||||
@@ -262,7 +262,7 @@ fn fold_on_a_flange_panel() {
|
||||
let b = bbox(&mut s);
|
||||
assert!(b["max"][2].as_f64().unwrap_or(99.0) < 25.0, "{b}");
|
||||
// Folding across the flange's own bend is refused.
|
||||
assert!(s.execute("SheetMetalFoldCmd", &json!({"points": [[50, y, 2], [50, y, 25]]})).is_err());
|
||||
assert!(s.execute("sheet.fold", &json!({"points": [[50, y, 2], [50, y, 25]]})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -270,51 +270,51 @@ fn fold_through_cut_outs() {
|
||||
let mut s = Session::default();
|
||||
base(&mut s, 100.0, 60.0);
|
||||
// A slot across the fold line (edges along and across the bend).
|
||||
run(&mut s, "SketchCreate", json!({"plane": "XY", "name": "Slot"}));
|
||||
run(&mut s, "ShapeRectangleTwoPoint", json!({"p0": [30, 20], "p1": [50, 40]}));
|
||||
run(&mut s, "SketchStop", json!({}));
|
||||
run(&mut s, "Extrude", json!({"sketch": "Slot", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY", "name": "Slot"}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0": [30, 20], "p1": [50, 40]}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "solid.extrude", json!({"sketch": "Slot", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
let mut plain = Session::default();
|
||||
base(&mut plain, 100.0, 60.0);
|
||||
fold_line(&mut plain);
|
||||
run(&mut plain, "SheetMetalFoldCmd", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
run(&mut plain, "sheet.fold", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
fold_line(&mut s);
|
||||
run(&mut s, "SheetMetalFoldCmd", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
run(&mut s, "sheet.fold", json!({"sketch": "FoldLine", "curve": "fl"}));
|
||||
let f = flat(&mut s);
|
||||
assert_eq!(f["cutouts"].as_array().map(Vec::len), Some(1), "{f}");
|
||||
let (v, vp) = (volume(&mut s), volume(&mut plain));
|
||||
// The slot takes 20 x 20 of the flat sheet; across the bend it removes the bend's share.
|
||||
assert!(v < vp - 900.0 && v > vp - 1100.0, "{v} {vp}");
|
||||
run(&mut s, "FusionSheetmetalUnfoldCommand", json!({}));
|
||||
run(&mut s, "sheet.unfold", json!({}));
|
||||
assert!((volume(&mut s) - (15000.0 - 1000.0)).abs() < 1e-3, "{}", volume(&mut s));
|
||||
// A round hole across the bend is not supported yet, and says so.
|
||||
let mut c = Session::default();
|
||||
base(&mut c, 100.0, 60.0);
|
||||
run(&mut c, "SketchCreate", json!({"plane": "XY", "name": "Hole"}));
|
||||
run(&mut c, "CircleCenterRadius", json!({"center": [40, 30], "radius": 5}));
|
||||
run(&mut c, "SketchStop", json!({}));
|
||||
run(&mut c, "Extrude", json!({"sketch": "Hole", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
run(&mut c, "sketch.create", json!({"plane": "XY", "name": "Hole"}));
|
||||
run(&mut c, "sketch.circle.center", json!({"center": [40, 30], "radius": 5}));
|
||||
run(&mut c, "sketch.finish", json!({}));
|
||||
run(&mut c, "solid.extrude", json!({"sketch": "Hole", "through_all": true, "operation": "cut", "direction": "symmetric"}));
|
||||
fold_line(&mut c);
|
||||
let e = c.execute("SheetMetalFoldCmd", &json!({"sketch": "FoldLine", "curve": "fl"})).map(|_| ()).unwrap_err().to_string();
|
||||
let e = c.execute("sheet.fold", &json!({"sketch": "FoldLine", "curve": "fl"})).map(|_| ()).unwrap_err().to_string();
|
||||
assert!(e.contains("not supported yet"), "{e}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flange_edges_are_named_and_follow_the_base_sketch() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "SketchCreate", json!({"plane": "XY", "name": "Base"}));
|
||||
run(&mut s, "ShapeRectangleTwoPoint", json!({"p0": [0, 0], "p1": [100, 60]}));
|
||||
let d = run(&mut s, "SketchDimension", json!({"entities": ["l1"], "value": 100}));
|
||||
run(&mut s, "SketchStop", json!({}));
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"sketch": "Base"}));
|
||||
run(&mut s, "FusionSheetMetalFlangeCommand", json!({"edges": [[100, 30, 2.5]], "height": 20, "name": "Side"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY", "name": "Base"}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0": [0, 0], "p1": [100, 60]}));
|
||||
let d = run(&mut s, "sketch.dimension", json!({"entities": ["l1"], "value": 100}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "sheet.flange", json!({"sketch": "Base"}));
|
||||
run(&mut s, "sheet.flange", json!({"edges": [[100, 30, 2.5]], "height": 20, "name": "Side"}));
|
||||
let side = s.doc.find_feature("Side").cloned().unwrap();
|
||||
assert_eq!(side.edge_names, vec!["base:l2:top".to_string()]);
|
||||
let v0 = volume(&mut s);
|
||||
// Narrower base: the flange stays on the right edge (now at x = 40).
|
||||
let name = d["param"].as_str().or_else(|| d["name"].as_str()).map(str::to_string).unwrap_or_else(|| "d1".into());
|
||||
run(&mut s, "ChangeParameterCommand", json!({"name": name, "expression": "40"}));
|
||||
let b = run(&mut s, "MeasureCommand", json!({}))["bodies"][0]["bbox"].clone();
|
||||
run(&mut s, "parameters.change", json!({"name": name, "expression": "40"}));
|
||||
let b = run(&mut s, "inspect.measure", json!({}))["bodies"][0]["bbox"].clone();
|
||||
let w = b["max"][0].as_f64().unwrap_or(0.0) - b["min"][0].as_f64().unwrap_or(0.0);
|
||||
assert!((w - 40.0).abs() < 1e-3 && b["max"][2].as_f64().unwrap_or(0.0) > 19.0, "{b}");
|
||||
assert!(volume(&mut s) < v0);
|
||||
@@ -323,7 +323,7 @@ fn flange_edges_are_named_and_follow_the_base_sketch() {
|
||||
// A hem on the flange's far edge is named after the flange.
|
||||
let top = b["max"][2].as_f64().unwrap_or(0.0);
|
||||
let x = b["max"][0].as_f64().unwrap_or(0.0);
|
||||
run(&mut s, "FusionSheetMetalHemFlangeCommand", json!({"edges": [[x, 30, top]], "length": 6, "name": "H"}));
|
||||
run(&mut s, "sheet.hem", json!({"edges": [[x, 30, top]], "length": 6, "name": "H"}));
|
||||
let h = s.doc.find_feature("H").cloned().unwrap();
|
||||
assert!(h.edge_names[0].starts_with(&format!("F{id}.0:far")), "{:?}", h.edge_names);
|
||||
}
|
||||
@@ -334,7 +334,7 @@ fn fold_keeps_the_larger_side_either_way() {
|
||||
for (w, line, moving_right) in [(60.0, 40.0, true), (100.0, 40.0, false)] {
|
||||
let mut s = Session::default();
|
||||
base(&mut s, w, 40.0);
|
||||
run(&mut s, "SheetMetalFoldCmd", json!({"points": [[line, 0, 2.5], [line, 40, 2.5]]}));
|
||||
run(&mut s, "sheet.fold", json!({"points": [[line, 0, 2.5], [line, 40, 2.5]]}));
|
||||
let b = bbox(&mut s);
|
||||
let (x0, x1) = (b["min"][0].as_f64().unwrap_or(0.0), b["max"][0].as_f64().unwrap_or(0.0));
|
||||
if moving_right {
|
||||
|
||||
Reference in new issue
Block a user