M0: desktop app: toolbar, browser, timeline, GPU viewport, view cube, sketch tools, dialogs, control channel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3714342737
commit
8a811f8eff
33 files changed
+7321
-32
No files matched your search
@@ -303,7 +303,9 @@ fn plane_ref(s: &Session, p: &Value, cmd: &str) -> Result<PlaneRef> {
|
||||
&& (fp - f.centroid).dot(n).abs() < tol * 10.0
|
||||
&& b.body.tessellate(tol).map(|m| face_contains(&m, f.index, fp, tol * 10.0)).unwrap_or(false)
|
||||
{
|
||||
found = Plane::from_normal(f.centroid + n * (fp - f.centroid).dot(n), n);
|
||||
// Sketch origin: the model origin projected onto the face plane.
|
||||
let d = (f.centroid + n * (fp - f.centroid).dot(n)).dot(n);
|
||||
found = Plane::from_normal(n * d, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
pub mod cmd;
|
||||
pub mod params;
|
||||
pub mod sample;
|
||||
pub mod view;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//! A sample design (used by `solvecraft --sample` and demos): a parametric plate with rounded
|
||||
//! corners, two holes and a boss.
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
pub fn script() -> Value {
|
||||
json!({"commands": [
|
||||
{"command": "ChangeParameterCommand", "params": {"name": "width", "expression": "80 mm", "comment": "plate width"}},
|
||||
{"command": "ChangeParameterCommand", "params": {"name": "depth", "expression": "50 mm"}},
|
||||
{"command": "ChangeParameterCommand", "params": {"name": "thickness", "expression": "8 mm"}},
|
||||
{"command": "SketchCreate", "params": {"plane": "XY", "name": "Base"}},
|
||||
{"command": "ShapeRectangleTwoPoint", "params": {"p0": [0, 0], "p1": [80, 50]}},
|
||||
{"command": "ConstraintCoincident", "params": {"a": "p1", "b": "origin"}},
|
||||
{"command": "SketchDimension", "params": {"entities": ["l1"], "value": "width"}},
|
||||
{"command": "SketchDimension", "params": {"entities": ["l2"], "value": "depth"}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": "thickness", "body_name": "Plate"}},
|
||||
{"command": "FusionFilletEdgesCommand", "params": {"edges": [[0, 0, 4], [80, 0, 4], [80, 50, 4], [0, 50, 4]], "radius": "6 mm"}},
|
||||
{"command": "SketchCreate", "params": {"plane": "XY", "name": "Holes"}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [12, 25], "diameter": 8}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [68, 25], "diameter": 8}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": "thickness", "operation": "cut", "name": "Holes"}},
|
||||
{"command": "SketchCreate", "params": {"plane": {"face": [40, 25, 8]}, "name": "Boss"}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [40, 25], "diameter": 24}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": 14, "operation": "join", "name": "Boss"}},
|
||||
{"command": "SketchCreate", "params": {"plane": {"face": [40, 37, 22]}, "name": "Bore"}},
|
||||
{"command": "CircleCenterRadius", "params": {"center": [40, 25], "diameter": 12}},
|
||||
{"command": "SketchStop", "params": {}},
|
||||
{"command": "Extrude", "params": {"distance": 22, "direction": "negative", "operation": "cut", "name": "Bore"}},
|
||||
]})
|
||||
}
|
||||
@@ -299,3 +299,16 @@ fn registry_is_consistent() {
|
||||
let s = Session::default();
|
||||
assert!(!find_command("DrawPolyline").unwrap().info(&s).enabled);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_design_builds() {
|
||||
let mut s = Session::default();
|
||||
s.run_script(&crate::sample::script()).unwrap();
|
||||
let m = run(&mut s, "MeasureCommand", json!({}));
|
||||
assert_eq!(m["body_count"], 1, "{m}");
|
||||
let plate = 80.0 * 50.0 * 8.0 - 4.0 * (36.0 - PI * 9.0) * 8.0 - 2.0 * PI * 16.0 * 8.0;
|
||||
let boss = PI * 144.0 * 14.0;
|
||||
let bore = PI * 36.0 * 22.0;
|
||||
let v = m["total"]["volume_mm3"].as_f64().unwrap();
|
||||
assert!(rel(v, plate + boss - bore) < 1e-3, "{v} vs {}", plate + boss - bore);
|
||||
}
|
||||
@@ -106,7 +106,10 @@ pub fn scene(s: &Session, cam: &Camera) -> Scene {
|
||||
let selected = s.selection.iter().any(|x| matches!(x, Sel::Body { name } if *name == body.name));
|
||||
let mesh = body.mesh();
|
||||
sc.meshes.push(SceneMesh { mesh: Arc::clone(&mesh), color: if selected { colors::BODY_SELECTED } else { colors::BODY } });
|
||||
for e in &mesh.edges {
|
||||
for (i, e) in mesh.edges.iter().enumerate() {
|
||||
if mesh.seams.get(i).copied().unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
sc.lines.push(SceneLine { points: e.clone(), color: colors::EDGE, width: 1.2, on_top: false });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user