Fix: rectangles over-constrained after an edit (dragged sides collapsed)
Parallel and perpendicular residuals were the cross/dot product over the sum of the line lengths, so the solver could satisfy them by shrinking a line to nothing. Dragging a corner of a rotated (3-point) rectangle collapsed a side to zero; every later dimension then conflicted. The residuals are now the sine or cosine of the angle (over the product of the lengths), which shrinking can't improve. Tests drag, dimension, pin and square center, 2-point and 3-point rectangles and check their degrees of freedom; oracle unchanged at 53/66. 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
c2309eb43b
commit
a6dc759a02
3 files changed
+111
-1
No files matched your search
@@ -274,7 +274,10 @@ fn residuals(s: &State, k: &ConstraintKind, out: &mut Vec<f64>) {
|
||||
let (a0, a1) = s.line(a);
|
||||
let (b0, b1) = s.line(b);
|
||||
let (da, db) = (a1 - a0, b1 - b0);
|
||||
let scale = (da.len() + db.len()).max(1e-12);
|
||||
// The sine (parallel) or cosine (perpendicular) of the angle between the lines:
|
||||
// independent of their lengths, so the solver can't satisfy it by shrinking a line
|
||||
// to nothing (scaling by the summed lengths did, collapsing dragged rectangles).
|
||||
let scale = (da.len() * db.len()).max(1e-12);
|
||||
let v = if matches!(k, Parallel { .. }) { da.cross(db) } else { da.dot(db) };
|
||||
out.push(v / scale);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user