forked from 1b-agent/opencadstudio-upstream
Keep opposite line endpoint fixed during grip edits
This commit is contained in:
1 parent
08bb17b0b8
commit
07d8d7eb00
3 files changed
+18
-22
No files matched your search
@@ -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();
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user