Files
OneCAD/crates/engine/src/cmd/sketch_symmetry_point_tests.rs
T
DuBearte 3e13eb6392 Sketch: symmetry about the origin point or an origin axis (#1318)
Fixes #1075. sketch.constraint.symmetry takes a centre point (the origin or any sketch point) as well as a line; the Symmetry tool's third pick may be the origin point or the sketch's own X/Y origin axis. Checked on main + this branch: cargo check --workspace, the engine cmd::sketch tests (257) and the UI symmetry pick tests.
2026-10-15 03:47:37 -04:00

88 lines
4.1 KiB
Rust

//! Symmetry about a point (#1075): the origin (or any sketch point) picked as the third entity,
//! or given as `point`. Each pair is joined by a construction line the point is the midpoint of.
use serde_json::{Value, json};
use solidcraft_geom::Vec2;
use solidcraft_sketch::{ConstraintKind, Sketch};
use crate::Session;
fn run(s: &mut Session, id: &str, p: Value) -> Value {
match s.execute(id, &p) {
Ok(v) => v,
Err(e) => panic!("{id} {p}: {e}"),
}
}
fn sketch(s: &Session) -> Sketch {
s.doc.sketch(s.active_sketch.unwrap()).unwrap().clone()
}
fn pt(sk: &Sketch, r: &str) -> Vec2 {
sk.point(sk.resolve_point(r).unwrap()).unwrap()
}
fn new_sketch() -> Session {
let mut s = Session::default();
run(&mut s, "sketch.create", json!({"plane": "XY"}));
s
}
#[test]
fn two_points_symmetric_about_the_origin() {
for params in [json!({"a": "p", "b": "q", "line": "origin"}), json!({"a": "p", "b": "q", "point": "origin"})] {
let mut s = new_sketch();
run(&mut s, "sketch.point", json!({"point": [10, 5], "id": "p"}));
run(&mut s, "sketch.point", json!({"point": [-12, -3], "id": "q"}));
let r = run(&mut s, "sketch.constraint.symmetry", params.clone());
let sk = sketch(&s);
// The first point stays; the second mirrors onto it through the origin.
assert!(pt(&sk, "p").dist(Vec2::new(10.0, 5.0)) < 1e-6, "{params}");
assert!(pt(&sk, "q").dist(Vec2::new(-10.0, -5.0)) < 1e-6, "{params}: {:?}", pt(&sk, "q"));
// One construction line, from p to q, with the origin at its midpoint.
let created = r["created"]["curves"].as_array().unwrap();
assert_eq!(created.len(), 1, "{r}");
let l = sk.curve_index(created[0].as_str().unwrap()).unwrap();
assert!(sk.curves[l].construction);
assert!(sk.constraints.iter().any(|k| k.kind == ConstraintKind::Midpoint { p: 0, l }));
// It holds: moving p moves q opposite.
run(&mut s, "sketch.drag", json!({"entity": "p", "from": [10, 5], "to": [20, 8]}));
let sk = sketch(&s);
assert!((pt(&sk, "p") + pt(&sk, "q")).len() < 1e-6, "{:?} {:?}", pt(&sk, "p"), pt(&sk, "q"));
}
}
#[test]
fn circles_and_lines_symmetric_about_a_point() {
let mut s = new_sketch();
run(&mut s, "sketch.point", json!({"point": [5, 5], "id": "c"}));
run(&mut s, "sketch.circle.center", json!({"center": [15, 5], "radius": 2, "id": "k1"}));
run(&mut s, "sketch.circle.center", json!({"center": [-4, 6], "radius": 3, "id": "k2"}));
run(&mut s, "sketch.constraint.symmetry", json!({"a": "k1", "b": "k2", "point": "c"}));
let sk = sketch(&s);
let (c1, c2) = (sk.center(sk.curve_index("k1").unwrap()).unwrap(), sk.center(sk.curve_index("k2").unwrap()).unwrap());
assert!(((c1 + c2) * 0.5).dist(Vec2::new(5.0, 5.0)) < 1e-6, "{c1:?} {c2:?}");
assert!((sk.radius(sk.curve_index("k1").unwrap()).unwrap() - sk.radius(sk.curve_index("k2").unwrap()).unwrap()).abs() < 1e-6);
// Two lines: each end pairs with the other line's end nearest its mirror image.
let mut s = new_sketch();
run(&mut s, "sketch.line", json!({"points": [[2, 1], [8, 4]], "ids": ["a"]}));
run(&mut s, "sketch.line", json!({"points": [[-7, -5], [-1, -1]], "ids": ["b"]}));
let r = run(&mut s, "sketch.constraint.symmetry", json!({"a": "a", "b": "b", "line": "origin"}));
assert_eq!(r["created"]["curves"].as_array().unwrap().len(), 2, "{r}");
let sk = sketch(&s);
assert!((pt(&sk, "a.start") + pt(&sk, "b.end")).len() < 1e-6);
assert!((pt(&sk, "a.end") + pt(&sk, "b.start")).len() < 1e-6);
}
#[test]
fn a_point_cannot_be_its_own_mirror() {
let mut s = new_sketch();
run(&mut s, "sketch.point", json!({"point": [10, 5], "id": "p"}));
let before = s.doc.to_json();
assert!(s.execute("sketch.constraint.symmetry", &json!({"a": "p", "b": "origin", "point": "origin"})).is_err());
assert!(s.execute("sketch.constraint.symmetry", &json!({"a": "p", "b": "p", "line": "origin"})).is_err());
assert!(s.execute("sketch.constraint.symmetry", &json!({"a": "p", "b": "origin", "point": "nope"})).is_err());
assert_eq!(s.doc.to_json(), before);
}