Sketch: drawing infers tangent (from an arc end) and perpendicular (from a line end) constraints; profile finding prefilters crossings by bounding box (text and free-form sketches 30x faster); large-sketch solver tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
346be40377
commit
3ab3e961de
4 files changed
+118
-6
No files matched your search
@@ -435,10 +435,17 @@ fn draw_line(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
if infer {
|
||||
let d = b.pos() - a.pos();
|
||||
if d.y.abs() <= d.len() * 1e-9 {
|
||||
let axis = if d.y.abs() <= d.len() * 1e-9 {
|
||||
cons.push(add_c(sk, ConstraintKind::Horizontal { l: c })?);
|
||||
true
|
||||
} else if d.x.abs() <= d.len() * 1e-9 {
|
||||
cons.push(add_c(sk, ConstraintKind::Vertical { l: c })?);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if let Some(k) = infer_at_start(sk, c, axis) {
|
||||
cons.push(add_c(sk, k)?);
|
||||
}
|
||||
}
|
||||
curves.push(c);
|
||||
@@ -449,6 +456,38 @@ fn draw_line(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(result((curves, cons), info))
|
||||
}
|
||||
|
||||
/// A relation the new line `c` has with the curve it starts from (drawn exactly so): tangent
|
||||
/// to an arc, or perpendicular to a line (parallel continuations are left alone). `axis`: the
|
||||
/// line already got horizontal/vertical, so a perpendicular to an axis-aligned line would be
|
||||
/// redundant.
|
||||
fn infer_at_start(sk: &Sketch, c: usize, axis: bool) -> Option<ConstraintKind> {
|
||||
let CurveKind::Line { a, b } = sk.curves.get(c)?.kind else { return None };
|
||||
let (pa, pb) = (sk.point(a)?, sk.point(b)?);
|
||||
let u = (pb - pa).normalized()?;
|
||||
for (i, o) in sk.curves.iter().enumerate() {
|
||||
if i == c || !o.kind.uses(a) {
|
||||
continue;
|
||||
}
|
||||
match o.kind {
|
||||
CurveKind::Arc { c: cc, .. } => {
|
||||
let r = (pa - sk.point(cc)?).normalized()?;
|
||||
if r.dot(u).abs() < 1e-9 {
|
||||
return Some(ConstraintKind::Tangent { a: i, b: c });
|
||||
}
|
||||
}
|
||||
CurveKind::Line { a: oa, b: ob } => {
|
||||
let v = (sk.point(ob)? - sk.point(oa)?).normalized()?;
|
||||
let o_axis = v.x.abs() < 1e-9 || v.y.abs() < 1e-9;
|
||||
if u.dot(v).abs() < 1e-9 && !(axis && o_axis) {
|
||||
return Some(ConstraintKind::Perpendicular { a: i, b: c });
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Closed polygon of lines through new or referenced corner points.
|
||||
fn polygon_lines(sk: &mut Sketch, corners: &[Vec2]) -> Result<(Vec<usize>, Vec<usize>)> {
|
||||
let pts: Vec<usize> = corners.iter().map(|c| sk.add_point(*c, None)).collect::<std::result::Result<_, _>>()?;
|
||||
|
||||
@@ -133,3 +133,16 @@ fn auto_constrain_fully_constrains_a_rough_sketch() {
|
||||
assert!(s.active_sketch.is_none());
|
||||
assert!(r["added"].as_array().unwrap().len() >= 3, "{r}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drawing_infers_tangent_and_perpendicular() {
|
||||
let mut s = new_sketch();
|
||||
let l1 = ids(&run(&mut s, "DrawPolyline", json!({"points": [[0, 0], [10, 10]], "infer": true}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("{l1}.end"), [20, 0]], "infer": true}));
|
||||
assert_eq!(r["constraints"].as_array().unwrap().len(), 1, "{r}");
|
||||
let a = ids(&run(&mut s, "ArcCenterTwoPoint", json!({"center": [50, 0], "start": [60, 0], "end": [50, 10]}))["curves"])[0].clone();
|
||||
let r = run(&mut s, "DrawPolyline", json!({"points": [format!("{a}.end"), [30, 10]], "infer": true}));
|
||||
let si = run(&mut s, "sketch.inspect", json!({}));
|
||||
let names: Vec<&str> = si["constraints"].as_array().unwrap().iter().map(|c| c["name"].as_str().unwrap()).collect();
|
||||
assert!(names.contains(&"Perpendicular") && names.contains(&"Tangent"), "{names:?} {r}");
|
||||
}
|
||||
Reference in new issue
Block a user