Drawing connects to existing points: a new point landing exactly on an existing point (the origin too) gets a coincident constraint in the engine, for every drawing command and every caller (MCP, scripts, clicks), in the same undo step; connect: false opts out. Re-tying an existing coincident returns it ("existing": true) instead of failing; the UI's after-the-fact tie_snaps is gone
This commit is contained in:
1 parent
448ea769eb
commit
5d5ff44db2
8 files changed
+141
-66
No files matched your search
@@ -242,38 +242,9 @@ fn run_shape(app: &mut SolveApp, t: &Tool) -> Vec<String> {
|
||||
.ok()
|
||||
.map(|v| v["curves"].as_array().into_iter().flatten().filter_map(|c| c.as_str().map(str::to_string)).collect())
|
||||
.unwrap_or_default();
|
||||
tie_snaps(app, t, &curves);
|
||||
curves
|
||||
}
|
||||
|
||||
/// A click that snapped to an existing point (the origin, a corner) but went in as plain
|
||||
/// coordinates: tie the new shape's point there to it, as Fusion does.
|
||||
fn tie_snaps(app: &mut SolveApp, t: &Tool, curves: &[String]) {
|
||||
let mut ties = Vec::new();
|
||||
{
|
||||
let st = app.session.world_state();
|
||||
let Some(ss) = app.session.active_sketch.and_then(|s| st.sketch(s)) else { return };
|
||||
let sk = &ss.sketch;
|
||||
let new_pts: Vec<usize> =
|
||||
curves.iter().filter_map(|c| sk.curve_index(c)).flat_map(|i| sk.curves.get(i).map(|c| c.kind.point_ids()).unwrap_or_default()).collect();
|
||||
for (at, r) in &t.pts {
|
||||
let Some(r) = r else { continue };
|
||||
let Some(target) = sk.resolve_point(r) else { continue };
|
||||
if new_pts.contains(&target) {
|
||||
continue;
|
||||
}
|
||||
if let Some(q) = new_pts.iter().copied().find(|q| sk.point(*q).is_some_and(|p| p.dist(*at) < 1e-6))
|
||||
&& let Some(qid) = sk.points.get(q).map(|p| p.id.clone())
|
||||
{
|
||||
ties.push((r.clone(), qid));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (a, b) in ties {
|
||||
let _ = app.run("sketch.constraint.coincident", json!({"a": a, "b": b}));
|
||||
}
|
||||
}
|
||||
|
||||
fn run_pick(app: &mut SolveApp, t: &Tool) {
|
||||
let k = &t.picks;
|
||||
let params = match t.cmd {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{"call": "engine.execute", "params": {"command": "sketch.create", "params": {"plane": "XY"}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.rectangle.two_point", "params": {"p0": [0, 0], "p1": [40, 20]}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.rectangle.two_point", "params": {"p0": [0, 0], "p1": [40, 20], "connect": false}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.circle.center", "params": {"center": [60, 10], "radius": 5}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.line", "params": {"points": [[45, -10], [75, -10]]}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.line", "params": {"points": [[45, 30], [75, 30]]}}},
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{"note": "A rectangle whose first corner is clicked on the origin is tied to it once (the engine connects it), so two dimensions fully constrain it."},
|
||||
{"start": "sketch.create"},
|
||||
{"click": {"plane": "XY"}},
|
||||
{"start": "sketch.rectangle.two_point"},
|
||||
{"click": {"sketch": [0, 0]}},
|
||||
{"click": {"sketch": [30, 20]}},
|
||||
{"key": "Escape"},
|
||||
{"expect": {"query": {"command": "sketch.inspect", "path": ["dof"], "value": 2}}},
|
||||
{"expect": {"query": {"command": "sketch.inspect", "path": ["constraints", 4, "type"], "value": "coincident"}}},
|
||||
{"expect": {"query": {"command": "sketch.inspect", "path": ["constraints", 5], "value": null}}},
|
||||
{"key": "Z", "cmd": true},
|
||||
{"expect": {"query": {"command": "sketch.inspect", "path": ["curves", 0], "value": null}}}
|
||||
]
|
||||
Reference in new issue
Block a user