fix(grips): compute grip positions in f64 so they sit on the wire

Grip markers drew visibly offset from the entity on large-coordinate
(UTM-scale) drawings: every Grippable impl cast the f64 entity coordinates
to f32 BEFORE the world-offset subtraction, and at 1e7 magnitude an f32
holds ~0.9 drawing units of rounding error. The wires subtract the offset
in f64 first (precision-preserving), so the grips landed up to ~1 unit
away from the geometry they belong to.

GripDef.world is now DVec3: producers fill it straight from the f64
entity data, refresh_selected_grips subtracts the world offset in f64,
and only the small offset-local result is cast to f32 for screen-space
projection (grips_to_screen / find_hit_grip) and drag state.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-11 00:04:37 +03:00
1 parent ed29933d87
commit 25715d1b03
33 files changed
+898 -817

No files matched your search

+6 -3
View File
@@ -437,9 +437,12 @@ impl OpenCADStudio {
let grips = dispatch::grips(entity)
.into_iter()
.map(|mut g| {
g.world.x -= wo[0] as f32;
g.world.y -= wo[1] as f32;
g.world.z -= wo[2] as f32;
// Subtract in f64: at UTM magnitudes an f32 cast before
// the offset costs ~1 unit and draws the grip off the
// wire.
g.world.x -= wo[0];
g.world.y -= wo[1];
g.world.z -= wo[2];
g
})
.collect();
+16 -9
View File
@@ -304,10 +304,13 @@ impl OpenCADStudio {
// header so the ✓ marks the right one (text/dim/mline come from
// the document header directly). DXF provides these via
// $CTABLESTYLE / $CMLEADERSTYLE; DWG leaves them at "Standard".
self.ribbon.active_table_style =
self.tabs[i].scene.document.header.current_table_style_name.clone();
self.tabs[i].active_mleader_style = self
.tabs[i]
self.ribbon.active_table_style = self.tabs[i]
.scene
.document
.header
.current_table_style_name
.clone();
self.tabs[i].active_mleader_style = self.tabs[i]
.scene
.document
.header
@@ -3838,8 +3841,8 @@ impl OpenCADStudio {
handle: popup.handle,
grip_id,
is_translate,
origin_world: g.world,
last_world: g.world,
origin_world: g.world.as_vec3(),
last_world: g.world.as_vec3(),
});
}
return Task::none();
@@ -3900,8 +3903,8 @@ impl OpenCADStudio {
handle: popup.handle,
grip_id: new_gid,
is_translate: false,
origin_world: g.world,
last_world: g.world,
origin_world: g.world.as_vec3(),
last_world: g.world.as_vec3(),
});
self.grip_add_provisional = Some((popup.handle, new_gid));
}
@@ -6746,7 +6749,11 @@ impl OpenCADStudio {
if exists {
// Staged: header field is the round-trip source of truth
// ($CMLEADERSTYLE); the ribbon/tab mirror it.
self.tabs[i].scene.document.header.current_mleader_style_name = name.clone();
self.tabs[i]
.scene
.document
.header
.current_mleader_style_name = name.clone();
self.tabs[i].active_mleader_style = name.clone();
self.ribbon.active_mleader_style = name.clone();
self.command_line