fix(pline): Convert to Arc follows the cursor and seats on click (#339)

Three fixes to the polyline arc-segment grip:

- bulge_from_midpoint keyed the sign off which chord side the midpoint
  lies on — the opposite convention of BulgeArc::from_bulge, so every
  grip-drag frame flipped the arc to the other side and the radius
  jumped wildly ("snaps to a restricted range of radii"). It now
  derives sign and sweep from the p0 -> mid -> p1 traversal
  orientation, verified as the exact inverse of BulgeArc's midpoint.

- The arc segment's mid grip dragged in Translate mode, feeding
  per-frame deltas through the recomputed arc midpoint — the drag
  deadlocked the moment the cursor crossed the chord. Arc grips now
  drag in Absolute mode: the arc re-fits through the cursor itself.
  Straight-segment grips keep the Translate stretch.

- Picking Convert to Arc in the grip menu now engages that segment
  grip (the Add Leader placement mechanic), so the new arc follows the
  mouse immediately and the next click seats it.

Closes #339

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Fable 5 committed 2026-07-22 12:15:36 +03:00
1 parent 41f7e2becf
commit d2be0c9bea
2 files changed
+45 -13

No files matched your search

+18
View File
@@ -981,6 +981,24 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
self.grip_add_provisional = Some((popup.handle, new_gid));
}
}
// Convert to Arc enters placement: the segment grip goes hot
// in Absolute mode, so the arc re-fits through the cursor as
// it moves and the next click seats it (#339).
if matches!(item.action, GripMenuAction::ConvertToArc) {
if let Some(g) = self.tabs[i]
.selected_grips
.iter()
.find(|g| g.id == popup.grip_id)
{
self.tabs[i].active_grip = Some(GripEdit {
handle: popup.handle,
grip_id: popup.grip_id,
is_translate: false,
origin_world: g.world,
last_world: g.world,
});
}
}
Task::none()
}