Keep opposite line endpoint fixed during grip edits

This commit is contained in:
Hakan Seven committed 2026-09-15 22:18:56 +03:00
1 parent 08bb17b0b8
commit 07d8d7eb00
3 files changed
+18 -22

No files matched your search

+4 -6
View File
@@ -1753,7 +1753,7 @@ impl OpenCADStudio {
.scene .scene
.document .document
.get_entity(target.handle)?; .get_entity(target.handle)?;
crate::scene::parametric_constraints::driven_ref_for_grip( crate::scene::parametric_constraints::grip_solve_anchor_ref(
entity, entity,
target.handle, target.handle,
target.grip_id, target.grip_id,
@@ -6141,11 +6141,9 @@ mod selection_preview_tests {
current[1], before[1], current[1], before[1],
"constrained neighbor must follow each grip frame" "constrained neighbor must follow each grip frame"
); );
let start_delta = current[0][0] - before[0][0]; assert_eq!(
let end_delta = current[0][1] - before[0][1]; current[0][0], before[0][0],
assert!( "the endpoint opposite the dragged grip must stay fixed"
(start_delta + end_delta).length_squared() > 1.0e-8,
"the opposite endpoint must not mirror the dragged endpoint around a fixed midpoint"
); );
} }
let _ = app.on_viewport_left_release(); let _ = app.on_viewport_left_release();
+9 -9
View File
@@ -83,17 +83,17 @@ impl ParametricRef {
} }
} }
/// Point reference driven by a native entity grip. Segment midpoint and /// Point reference temporarily pinned while solving a native grip edit.
/// scalar radius grips deliberately return None because they do not identify /// A line endpoint anchors its opposite endpoint so the grabbed endpoint is
/// one stored point parameter. /// projected onto the constraint solution instead of moving the whole line.
pub(crate) fn driven_ref_for_grip( pub(crate) fn grip_solve_anchor_ref(
entity: &acadrust::EntityType, entity: &acadrust::EntityType,
handle: Handle, handle: Handle,
grip_id: usize, grip_id: usize,
) -> Option<ParametricRef> { ) -> Option<ParametricRef> {
match entity { match entity {
acadrust::EntityType::Line(_) if grip_id <= 1 => { acadrust::EntityType::Line(_) if grip_id <= 1 => {
Some(ParametricRef::point(handle, grip_id as i32)) Some(ParametricRef::point(handle, 1 - grip_id as i32))
} }
acadrust::EntityType::LwPolyline(polyline) if grip_id < polyline.vertices.len() => { acadrust::EntityType::LwPolyline(polyline) if grip_id < polyline.vertices.len() => {
Some(ParametricRef::point(handle, grip_id as i32)) Some(ParametricRef::point(handle, grip_id as i32))
@@ -1888,18 +1888,18 @@ mod tests {
)); ));
assert_eq!( assert_eq!(
driven_ref_for_grip(&arc, handle, 0), grip_solve_anchor_ref(&arc, handle, 0),
Some(ParametricRef::center(handle)) Some(ParametricRef::center(handle))
); );
assert_eq!( assert_eq!(
driven_ref_for_grip(&arc, handle, 1), grip_solve_anchor_ref(&arc, handle, 1),
Some(ParametricRef::point(handle, 0)) Some(ParametricRef::point(handle, 0))
); );
assert_eq!( assert_eq!(
driven_ref_for_grip(&arc, handle, 2), grip_solve_anchor_ref(&arc, handle, 2),
Some(ParametricRef::point(handle, 1)) Some(ParametricRef::point(handle, 1))
); );
assert_eq!(driven_ref_for_grip(&arc, handle, 3), None); assert_eq!(grip_solve_anchor_ref(&arc, handle, 3), None);
} }
#[test] #[test]
+5 -7
View File
@@ -1942,10 +1942,10 @@ fn solve_scope(
sys.add_constraint(Rc::new(Difference::new(el.center.y, el.focus1.y, dy))); sys.add_constraint(Rc::new(Difference::new(el.center.y, el.focus1.y, dy)));
} }
// The first ordered Coincident selection is the anchor for this solve. // Temporarily make each requested anchor a fixed kernel input. Marking the
// Pin either its addressed point or every defining parameter of its whole // geometry parameters as driven keeps them exact and out of the solver's
// curve temporarily; the relation remains persistent, while these pins do // free-variable list; an approximate equality equation would still allow
// not enter the drawing's constraint graph. // visible drift after repeated grip frames.
for reference in driven_refs { for reference in driven_refs {
if !set if !set
.constraints .constraints
@@ -1996,9 +1996,7 @@ fn solve_scope(
} }
}; };
for parameter in params_to_pin { for parameter in params_to_pin {
let value = sys.store().get(parameter); sys.store_mut().set_driven(parameter, true);
let target = sys.add_param(value, true);
sys.add_constraint(Rc::new(Equal::new(parameter, target, 1.0)));
} }
} }