Rectangles name their sides and corners: sketch.rectangle.two_point and .center return sides {bottom, right, top, left} (line ids) and corners {bottom_left, bottom_right, top_right, top_left} (point ids), so they can be dimensioned without a sketch.inspect round trip
This commit is contained in:
1 parent
d57e90a32a
commit
49d6682fe7
2 files changed
+70
-9
No files matched your search
@@ -27,7 +27,7 @@ pub static COMMANDS: &[CommandSpec] = &[
|
||||
.icon("rect")
|
||||
.key("R")
|
||||
.enabled(in_sketch)
|
||||
.params("p0, p1: opposite corners [x,y]; construction?"),
|
||||
.params("p0, p1: opposite corners [x,y]; construction?. Returns sides {bottom, right, top, left} (line ids) and corners {bottom_left, bottom_right, top_right, top_left} (point ids)"),
|
||||
CommandSpec::new("sketch.rectangle.three_point", "3-Point Rectangle", rect_three_point)
|
||||
.at("SKETCH", "CREATE")
|
||||
.icon("rect3")
|
||||
@@ -37,7 +37,7 @@ pub static COMMANDS: &[CommandSpec] = &[
|
||||
.at("SKETCH", "CREATE")
|
||||
.icon("rect_center")
|
||||
.enabled(in_sketch)
|
||||
.params("center, corner"),
|
||||
.params("center, corner. Returns sides {bottom, right, top, left} (line ids) and corners {bottom_left, bottom_right, top_right, top_left} (point ids)"),
|
||||
CommandSpec::new("sketch.circle.center", "Center Diameter Circle", circle_center)
|
||||
.at("SKETCH", "CREATE")
|
||||
.icon("circle")
|
||||
@@ -526,6 +526,27 @@ fn rect_constraints(sk: &mut Sketch, l: &[usize]) -> Result<Vec<String>> {
|
||||
Ok(cons)
|
||||
}
|
||||
|
||||
/// Which side and corner of an axis-aligned rectangle is which, from its lines and corner
|
||||
/// points as `polygon_lines` made them (counter-clockwise from the bottom-left corner), so a
|
||||
/// caller can dimension it without inspecting the sketch first.
|
||||
fn rect_names(sk: &Sketch, l: &[usize], pts: &[usize]) -> Value {
|
||||
let curve = |i: usize| l.get(i).and_then(|c| sk.curves.get(*c)).map(|c| c.id.clone());
|
||||
let point = |i: usize| pts.get(i).and_then(|q| sk.points.get(*q)).map(|q| q.id.clone());
|
||||
json!({
|
||||
"sides": {"bottom": curve(0), "right": curve(1), "top": curve(2), "left": curve(3)},
|
||||
"corners": {"bottom_left": point(0), "bottom_right": point(1), "top_right": point(2), "top_left": point(3)},
|
||||
})
|
||||
}
|
||||
|
||||
/// `result` plus the rectangle's named sides and corners.
|
||||
fn rect_result(sk_out: (Vec<String>, Vec<String>), names: Value, info: Value) -> Value {
|
||||
let mut out = result(sk_out, info);
|
||||
if let (Some(o), Value::Object(n)) = (out.as_object_mut(), names) {
|
||||
o.extend(n);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn rect_two_point(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let cmd = "sketch.rectangle.two_point";
|
||||
let (a, b) = (req_vec2(cmd, p, "p0")?, req_vec2(cmd, p, "p1")?);
|
||||
@@ -533,13 +554,13 @@ fn rect_two_point(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
return Err(bad(cmd, "the corners must differ in x and y"));
|
||||
}
|
||||
let (lo, hi) = (Vec2::new(a.x.min(b.x), a.y.min(b.y)), Vec2::new(a.x.max(b.x), a.y.max(b.y)));
|
||||
let (out, info) = edit(s, p, cmd, false, |sk, _| {
|
||||
let (l, _) = polygon_lines(sk, &[lo, Vec2::new(hi.x, lo.y), hi, Vec2::new(lo.x, hi.y)])?;
|
||||
let ((out, names), info) = edit(s, p, cmd, false, |sk, _| {
|
||||
let (l, pts) = polygon_lines(sk, &[lo, Vec2::new(hi.x, lo.y), hi, Vec2::new(lo.x, hi.y)])?;
|
||||
let cons = rect_constraints(sk, &l)?;
|
||||
mark_construction(sk, &l, p);
|
||||
Ok((ids_of(sk, &l), cons))
|
||||
Ok(((ids_of(sk, &l), cons), rect_names(sk, &l, &pts)))
|
||||
})?;
|
||||
Ok(result(out, info))
|
||||
Ok(rect_result(out, names, info))
|
||||
}
|
||||
|
||||
fn rect_center(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
@@ -549,7 +570,7 @@ fn rect_center(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if h.x < 1e-9 || h.y < 1e-9 {
|
||||
return Err(bad(cmd, "the corner must differ from the centre in x and y"));
|
||||
}
|
||||
let (out, info) = edit(s, p, cmd, false, |sk, _| {
|
||||
let ((out, names), info) = edit(s, p, cmd, false, |sk, _| {
|
||||
let (l, pts) = polygon_lines(sk, &[c - h, Vec2::new(c.x + h.x, c.y - h.y), c + h, Vec2::new(c.x - h.x, c.y + h.y)])?;
|
||||
let mut cons = rect_constraints(sk, &l)?;
|
||||
// Both diagonals (construction), the centre at their crossing. Only the first carries
|
||||
@@ -567,9 +588,9 @@ fn rect_center(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
cons.push(add_c(sk, ConstraintKind::Midpoint { p: cp, l: diag })?);
|
||||
}
|
||||
mark_construction(sk, &l, p);
|
||||
Ok((ids_of(sk, &l), cons))
|
||||
Ok(((ids_of(sk, &l), cons), rect_names(sk, &l, &pts)))
|
||||
})?;
|
||||
Ok(result(out, info))
|
||||
Ok(rect_result(out, names, info))
|
||||
}
|
||||
|
||||
fn rect_three_point(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
@@ -1847,3 +1847,43 @@ fn boundary_fill_cells() {
|
||||
assert!(rel(m["total"]["volume_mm3"].as_f64().unwrap_or(0.0), 2.0 * 10.0 * 20.0 * 20.0) < 1e-9, "{m}");
|
||||
assert!(s.execute("SurfaceSculpt", &json!({"tools": ["A"], "cells": [[100, 100, 100]]})).is_err());
|
||||
}
|
||||
|
||||
/// Rectangles name their sides and corners, so they can be dimensioned without inspecting the
|
||||
/// sketch first, whichever way round the corners were given.
|
||||
#[test]
|
||||
fn rectangle_names_sides_and_corners() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY"}));
|
||||
let r = run(&mut s, "sketch.rectangle.two_point", json!({"p0": [40, 30], "p1": [0, 0]}));
|
||||
let pos = |s: &Session, id: &Value| {
|
||||
let sk = s.doc.sketch(s.active_sketch.unwrap()).unwrap();
|
||||
sk.point(sk.resolve_point(id.as_str().unwrap()).unwrap()).unwrap()
|
||||
};
|
||||
for (corner, at) in [("bottom_left", [0.0, 0.0]), ("bottom_right", [40.0, 0.0]), ("top_right", [40.0, 30.0]), ("top_left", [0.0, 30.0])] {
|
||||
let p = pos(&s, &r["corners"][corner]);
|
||||
assert!((p.x - at[0]).abs() < 1e-9 && (p.y - at[1]).abs() < 1e-9, "{corner}: {p:?} in {r}");
|
||||
}
|
||||
for (side, from, to) in [
|
||||
("bottom", "bottom_left", "bottom_right"),
|
||||
("right", "bottom_right", "top_right"),
|
||||
("top", "top_right", "top_left"),
|
||||
("left", "top_left", "bottom_left"),
|
||||
] {
|
||||
let line = r["sides"][side].as_str().unwrap();
|
||||
assert!(r["curves"].as_array().unwrap().iter().any(|c| c == line), "{r}");
|
||||
assert_eq!(pos(&s, &json!(format!("{line}.start"))), pos(&s, &r["corners"][from]), "{side} in {r}");
|
||||
assert_eq!(pos(&s, &json!(format!("{line}.end"))), pos(&s, &r["corners"][to]), "{side} in {r}");
|
||||
}
|
||||
run(&mut s, "sketch.constraint.coincident", json!({"a": r["corners"]["bottom_left"], "b": "origin"}));
|
||||
run(&mut s, "sketch.dimension", json!({"entities": [r["sides"]["bottom"]], "value": 50}));
|
||||
run(&mut s, "sketch.dimension", json!({"entities": [r["sides"]["left"]], "value": 20}));
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
assert_eq!(si["dof"], 0, "{si}");
|
||||
let p = pos(&s, &r["corners"]["top_right"]);
|
||||
assert!((p.x - 50.0).abs() < 1e-6 && (p.y - 20.0).abs() < 1e-6, "{p:?}");
|
||||
|
||||
let c = run(&mut s, "sketch.rectangle.center", json!({"center": [100, 0], "corner": [90, 5]}));
|
||||
let p = pos(&s, &c["corners"]["bottom_left"]);
|
||||
assert!((p.x - 90.0).abs() < 1e-9 && (p.y + 5.0).abs() < 1e-9, "{c}");
|
||||
assert_eq!(pos(&s, &json!(format!("{}.start", c["sides"]["top"].as_str().unwrap()))), pos(&s, &c["corners"]["top_right"]), "{c}");
|
||||
}
|
||||
Reference in new issue
Block a user