Sketch fillet and chamfer: a construction line at the corner is not a side (#1026).
This commit is contained in:
1 parent
8f081679bc
commit
1337404c06
2 files changed
+34
-2
No files matched your search
@@ -488,9 +488,13 @@ fn corner(sk: &Sketch, p: &Value, cmd: &str) -> Result<(usize, usize, usize, usi
|
||||
let (la, lb) = if let Some(r) = str_(p, "point") {
|
||||
let q = sk.resolve_point(r).ok_or_else(|| bad(cmd, format!("unknown point `{r}`")))?;
|
||||
let lines: Vec<usize> = (0..sk.curves.len()).filter(|i| ends(*i).is_some_and(|(a, b)| a == q || b == q) && !sk.is_linked_curve(*i)).collect();
|
||||
match lines[..] {
|
||||
// A construction line ending there too (a diagonal that centres something) is not one of
|
||||
// the corner's sides: it keeps its end on the virtual sharp corner (#1026).
|
||||
let sides: Vec<usize> =
|
||||
if lines.len() == 2 { lines } else { lines.into_iter().filter(|i| sk.curves.get(*i).is_some_and(|c| !c.construction)).collect() };
|
||||
match sides[..] {
|
||||
[a, b] => (a, b),
|
||||
_ => return Err(bad(cmd, "the corner must join exactly two lines")),
|
||||
_ => return Err(bad(cmd, "the corner must join exactly two lines (or give the two lines as `a` and `b`)")),
|
||||
}
|
||||
} else {
|
||||
let a = str_(p, "a").and_then(|i| sk.curve_index(i)).ok_or_else(|| bad(cmd, "`a` must be a line"))?;
|
||||
|
||||
@@ -678,6 +678,34 @@ fn ellipse_radii_dimensions() {
|
||||
assert!((a - std::f64::consts::PI * 60.0).abs() < 1e-6, "{a}");
|
||||
}
|
||||
|
||||
/// #1026: a construction diagonal ending at a rectangle's corner is not one of the corner's
|
||||
/// sides. The corner is rounded, and the diagonal keeps its end on the virtual sharp corner.
|
||||
#[test]
|
||||
fn fillet_a_corner_a_construction_diagonal_ends_in() {
|
||||
let mut s = new_sketch();
|
||||
run(&mut s, "sketch.line", json!({"points": [[0, 0], [50, 0], [50, 30], [0, 30]], "closed": true, "ids": ["a", "b", "c", "d"]}));
|
||||
let diag = ids(&run(&mut s, "sketch.line", json!({"points": ["c.end", "a.end"], "construction": true}))["curves"])[0].clone();
|
||||
let f = run(&mut s, "sketch.fillet", json!({"point": "a.end", "radius": 2}));
|
||||
let arc = ids(&f["curves"])[0].clone();
|
||||
let sk = sketch(&s);
|
||||
let ai = sk.curve_index(&arc).unwrap();
|
||||
assert!((sk.radius(ai).unwrap() - 2.0).abs() < 1e-7);
|
||||
let c = sk.center(ai).unwrap();
|
||||
assert!(c.dist(Vec2::new(48.0, 2.0)) < 1e-6, "{c:?}");
|
||||
// The diagonal still runs from (0, 30) to the sharp corner (50, 0).
|
||||
let di = sk.curve_index(&diag).unwrap();
|
||||
let Some(CurveKind::Line { a, b }) = sk.curves.get(di).map(|x| &x.kind) else { panic!("the diagonal is a line") };
|
||||
let (pa, pb) = (sk.point(*a).unwrap(), sk.point(*b).unwrap());
|
||||
assert!(pa.dist(Vec2::new(0.0, 30.0)) < 1e-6 && pb.dist(Vec2::new(50.0, 0.0)) < 1e-6, "{pa:?} {pb:?}");
|
||||
assert!(sk.curves.get(di).unwrap().construction);
|
||||
// Three lines at a corner, none of them construction, stay ambiguous.
|
||||
let mut s = new_sketch();
|
||||
run(&mut s, "sketch.line", json!({"points": [[0, 0], [50, 0], [50, 30]], "ids": ["a", "b"]}));
|
||||
run(&mut s, "sketch.line", json!({"points": ["a.end", [80, 20]]}));
|
||||
let e = s.execute("sketch.fillet", &json!({"point": "a.end", "radius": 2})).unwrap_err().to_string();
|
||||
assert!(e.contains("exactly two lines") && e.contains("`a` and `b`"), "{e}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fillet_a_line_and_an_arc() {
|
||||
let mut s = new_sketch();
|
||||
|
||||
Reference in new issue
Block a user