forked from 1b-agent/opencadstudio-upstream
fix(constraints): point symmetry converges from any start
Symmetric held the connecting direction perpendicular to the axis with the kernel's angle-based Perpendicular, which locks its turn side at construction: a point starting far from its mirror image had to swing the pair through the axis direction, the residual wrapped, and the solver stalled with the point unmoved. The perpendicularity is now the projection of the pair onto the axis direction being zero, a polynomial residual the solver follows from anywhere. Circle centers and ellipse centers use the same equation. tests/parametric_constraints_solve.rs symmetric_constraint_mirrors_one_circles_center_across_the_axis_line passes again. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
ececb0ef8c
commit
e537a495c6
1 file changed
+13
-11
@@ -1466,13 +1466,23 @@ fn build_constraint(
|
||||
let Some(mirror) = whole_line(sys, cache, *m) else {
|
||||
return Vec::new();
|
||||
};
|
||||
// The connecting direction is held perpendicular to the axis as a
|
||||
// projection onto the axis direction being zero: a polynomial
|
||||
// residual the solver can follow from any start. The angle form
|
||||
// (`Perpendicular`) locks its turn side at construction and stalls
|
||||
// when the pair has to swing through the axis direction — a point
|
||||
// starting far from its mirror image never arrived.
|
||||
let across_axis = |sys: &mut System, pa: GPoint, pb: GPoint| -> Rc<dyn Constraint> {
|
||||
let zero = sys.add_param(0.0, true);
|
||||
Rc::new(ProjectedDistanceAlongLine::new(pa, pb, zero, mirror, false))
|
||||
};
|
||||
if let (Some(pa), Some(pb)) =
|
||||
(point_ref(sys, cache, *a), point_ref(sys, cache, *b))
|
||||
{
|
||||
let pair = GLine { p1: pa, p2: pb };
|
||||
return vec![
|
||||
Rc::new(MidpointOnLine::new(pair, mirror)),
|
||||
Rc::new(PerpendicularConstraint::new(sys.store(), pair, mirror)),
|
||||
across_axis(sys, pa, pb),
|
||||
];
|
||||
}
|
||||
let (Some(first), Some(second)) = (
|
||||
@@ -1500,11 +1510,7 @@ fn build_constraint(
|
||||
};
|
||||
vec![
|
||||
Rc::new(MidpointOnLine::new(centers, mirror)),
|
||||
Rc::new(PerpendicularConstraint::new(
|
||||
sys.store(),
|
||||
centers,
|
||||
mirror,
|
||||
)),
|
||||
across_axis(sys, first.center, second.center),
|
||||
Rc::new(Equal::new(second.rad, first.rad, 1.0)),
|
||||
]
|
||||
}
|
||||
@@ -1523,11 +1529,7 @@ fn build_constraint(
|
||||
};
|
||||
vec![
|
||||
Rc::new(MidpointOnLine::new(centers, mirror)),
|
||||
Rc::new(PerpendicularConstraint::new(
|
||||
sys.store(),
|
||||
centers,
|
||||
mirror,
|
||||
)),
|
||||
across_axis(sys, first.center, second.center),
|
||||
Rc::new(SymmetricLineDirections::new(
|
||||
sys.store(),
|
||||
first_axis,
|
||||
|
||||
Reference in new issue
Block a user