app
SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
//! OFFSET ENTITIES AND SKETCH REGIONS (0.11.4) through the whole bridge, in the
//! SIMULATOR. What the simulator can honestly model it models exactly: the
//! offset of a plain block's face (a rectangle moved in or out) and the
//! regions of profiles that nest or stand apart. Anything else — a face whose
//! outline only SOLIDWORKS knows, contours that CROSS — it refuses, saying so;
//! the CSWA Step 4 spec runs those live. Every step says proven.live:false
//! until a live run measures it.
mod common;
use common::{Bridge, TempDir};
use serde_json::{json, Value};
const PI: f64 = std::f64::consts::PI;
fn s(v: &Value) -> String {
serde_json::to_string_pretty(v).unwrap_or_default()
}
fn boot(tag: &str) -> (Bridge, TempDir) {
let machine = TempDir::new(tag);
std::fs::write(machine.join("windows.json"), "[]").unwrap();
let b = Bridge::start_with(&[("SWX_LAUNCH_FAKE_DIR", &machine.path())]);
b.call("swx_start", json!({}));
(b, machine)
}
fn near(a: &Value, b: f64, rel: f64) -> bool {
a.as_f64().map(|x| (x - b).abs() <= rel * b.abs().max(1e-9)).unwrap_or(false)
}
fn volume(b: &Bridge) -> Value {
b.call("swx_mass_properties", json!({}))["volumeMm3"].clone()
}
#[test]
fn an_offset_of_a_plain_blocks_face_is_its_rectangle_moved_in_or_out() {
let (b, _m) = boot("regions-offset");
let block = json!([
{"op": "new_part"},
{"op": "sketch_rect", "plane": "Top Plane", "widthMm": 60, "heightMm": 40, "anchor": "center"},
{"op": "extrude", "depthMm": 20}
]);
// INWARD: the top face's outline 2 mm in, cut 5 deep — a pocket 56 x 36.
let mut script = block.as_array().unwrap().clone();
script.push(json!({"op": "sketch", "face": {"atPointMm": [0, 20, 0]}, "entities": [{"offsetEntities": {"fromFace": {"atPointMm": [0, 20, 0]}, "offsetMm": -2}}]}));
script.push(json!({"op": "cut", "depthMm": 5}));
let r = b.call("swx_run_script", json!({"script": script}));
check!(b, "the inward offset of a block's top face pockets it", r["success"] == true, s(&r));
let sk = &r["steps"][3]["result"];
check!(
b,
"the step names the offset, the side it landed on, and that the simulator drew a rectangle",
sk["offsets"][0]["offsetEntities"]["side"] == "inward" && sk["offsets"][0]["drawn"]["side"] == "inward"
&& [(0usize, 0usize, -28.0), (0, 1, -18.0), (1, 0, 28.0), (1, 1, 18.0)].iter().all(|(i, j, want)| near(&sk["offsets"][0]["drawn"]["rectMm"][*i][*j], *want, 1e-12))
&& near(&sk["profileAreaMm2"], 56.0 * 36.0, 1e-12),
s(sk)
);
check!(
b,
"...and is classified as an outer-loop offset, not yet measured live",
sk["proven"]["variants"].as_array().map(|a| a.iter().any(|v| v == "sketch.offsetEntities.outer")).unwrap_or(false)
&& sk["proven"]["live"] == false,
s(&sk["proven"])
);
check!(b, "the pocket removed 56 x 36 x 5 (swx_mass_properties)", near(&volume(&b), 60.0 * 40.0 * 20.0 - 56.0 * 36.0 * 5.0, 1e-6), s(&volume(&b)));
// OUTWARD, every loop: the bottom face's outline 3 mm out, a 4-deep boss below.
let mut script = block.as_array().unwrap().clone();
script.push(json!({"op": "sketch", "face": {"atPointMm": [0, 0, 0]}, "entities": [{"offsetEntities": {"fromFace": {"atPointMm": [0, 0, 0]}, "offsetMm": 3, "loops": "all"}}]}));
script.push(json!({"op": "extrude", "depthMm": 4}));
let r = b.call("swx_run_script", json!({"script": script}));
check!(
b,
"the outward offset of the bottom face is a 66 x 46 boss below it, classified as a face offset",
r["success"] == true && near(&volume(&b), 60.0 * 40.0 * 20.0 + 66.0 * 46.0 * 4.0, 1e-6)
&& r["steps"][3]["result"]["proven"]["variants"].as_array().map(|a| a.iter().any(|v| v == "sketch.offsetEntities.face")).unwrap_or(false),
format!("{}\n{}", s(&r), s(&volume(&b)))
);
// A face whose outline is SOLIDWORKS' own (a cylinder's end, a cut block)
// is refused — the simulator never invents an outline.
let r = b.call("swx_run_script", json!({"script": [
{"op": "new_part"},
{"op": "sketch_circle", "plane": "Top Plane", "radiusMm": 10},
{"op": "extrude", "depthMm": 5},
{"op": "sketch", "face": {"atPointMm": [0, 5, 0]}, "entities": [{"offsetEntities": {"fromFace": {"atPointMm": [0, 5, 0]}, "offsetMm": -1}}]},
{"op": "cut", "depthMm": 1}
]}));
check!(
b,
"an offset of a face that is not a plain block's is refused, naming why (and saying it runs live)",
r["success"] == false && r["error"].as_str().unwrap_or("").contains("plain block") && r["error"].as_str().unwrap_or("").contains("run it live"),
s(&r)
);
}
#[test]
fn a_region_pick_extrudes_only_the_regions_that_hold_its_points() {
let (b, _m) = boot("regions-pick");
let run = |b: &Bridge, entities: Value, extrude: Value| -> Value {
b.call("swx_run_script", json!({"script": [
{"op": "new_part"},
{"op": "sketch", "plane": "Front Plane", "entities": entities},
extrude
]}))
};
let two = json!([{"rect": {"xMm": 0, "yMm": 0, "widthMm": 10, "heightMm": 10}}, {"rect": {"xMm": 20, "yMm": 0, "widthMm": 10, "heightMm": 10}}]);
let r = run(&b, two.clone(), json!({"op": "extrude", "depthMm": 5, "regionsAtMm": [[25, 5]]}));
check!(b, "one of two rectangles picked: only it is extruded", r["success"] == true && near(&volume(&b), 500.0, 1e-9), format!("{}\n{}", s(&r), s(&volume(&b))));
check!(
b,
"the extrude is classified as a region pick (not yet measured live)",
r["steps"][2]["result"]["proven"]["variants"] == json!(["extrude.one", "extrude.regions"]) && r["steps"][2]["result"]["proven"]["live"] == false,
s(&r["steps"][2])
);
let r = run(&b, two, json!({"op": "extrude", "depthMm": 5, "regionsAtMm": [[25, 5], [5, 5]]}));
check!(b, "both picked: both", r["success"] == true && near(&volume(&b), 1000.0, 1e-9), s(&volume(&b)));
let ring = json!([{"circle": {"radiusMm": 10}}, {"circle": {"radiusMm": 5}}]);
let r = run(&b, ring.clone(), json!({"op": "extrude", "depthMm": 2, "regionAtMm": [0, 0]}));
check!(b, "a point inside the inner circle picks the DISC", r["success"] == true && near(&volume(&b), PI * 25.0 * 2.0, 1e-6), s(&volume(&b)));
let r = run(&b, ring, json!({"op": "extrude", "depthMm": 2, "regionAtMm": [7, 0]}));
check!(b, "a point between the circles picks the RING", r["success"] == true && near(&volume(&b), PI * 75.0 * 2.0, 1e-6), s(&volume(&b)));
let r = run(&b, json!([{"rect": {"xMm": 0, "yMm": 0, "widthMm": 10, "heightMm": 10}}]), json!({"op": "extrude", "depthMm": 2, "regionAtMm": [50, 50]}));
check!(b, "a point in no profile is refused, naming it", r["success"] == false && r["error"].as_str().unwrap_or("").contains("in no closed profile"), s(&r));
let crossing = json!([{"rect": {"xMm": 0, "yMm": 0, "widthMm": 10, "heightMm": 10}}, {"circle": {"centerMm": [10, 5], "radiusMm": 4}}]);
let r = run(&b, crossing, json!({"op": "extrude", "depthMm": 2, "regionAtMm": [2, 2]}));
check!(
b,
"CROSSING contours are SOLIDWORKS' to resolve: refused in the simulator, saying so",
r["success"] == false && r["error"].as_str().unwrap_or("").contains("CROSS") && r["error"].as_str().unwrap_or("").contains("run it live"),
s(&r)
);
}