forked from 1b-agent/opencadstudio-upstream
fix(snap): f64-precise computed snaps + UTM-tolerant cull + f64 previews
Computed snaps (midpoint/nearest/perpendicular/intersection/extension/ apparent/grid) reconstructed the snap point from f32 `wire.points` (absolute high half), so at UTM-scale they landed ~0.5 m off the geometry while endpoint/center (sourced from f64 key_vertices/snap_pts) stayed correct. Now they rebuild each vertex from points + points_low (the double-single low residual) and run the geometry in f64: - snap() cursor + geometry helpers (nearest_on_segment, perp_foot, seg_intersect_xy, extension_snap) are DVec3; wp_f64() reconstructs each vertex; midpoint uses f64 key_vertices directly (was downcast to f32). - snap callers pass the precise DVec3 cursor. Snap capture at deep zoom: the wire-AABB cull compared a sub-millimetre snap radius against f32 bounds quantized by ~1 ulp (~0.7 m at 5.7e6), wrongly excluding wires under the cursor. Pad the cull by the bound's own f32 quantization so it never rejects an in-range wire. Rubber-band previews (line/circle/arc/ellipse/rect/polygon) built f32 absolute points with an empty points_low, so the wire pass (relative-to- eye) drew them ~0.5 m off the cursor at UTM. Add WireModel::solid_f64, which splits f64 points into the double-single high/low pair; previews now track the cursor exactly. Known: snapping at extreme zoom on large drawings spikes CPU (per-move snap cost) — deferred. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
4f7a98a2ad
commit
bca8958025
8 files changed
+166
-158
No files matched your search
@@ -98,6 +98,34 @@ impl WireModel {
|
||||
f32::INFINITY,
|
||||
];
|
||||
|
||||
/// Double-single split: `high + low ≈ v` to ~f64 precision in two f32s.
|
||||
/// Matches the renderer's relative-to-eye reconstruction.
|
||||
#[inline]
|
||||
pub fn split_ds(v: f64) -> (f32, f32) {
|
||||
let high = v as f32;
|
||||
(high, (v - high as f64) as f32)
|
||||
}
|
||||
|
||||
/// Create a solid preview wire from f64 points, filling the double-single
|
||||
/// `points_low` buffer so the line stays precise at UTM-scale coordinates.
|
||||
/// Rubber-band previews built straight from f32 absolute points jitter
|
||||
/// ~0.5 m at UTM because the wire pass is relative-to-eye and expects the
|
||||
/// low residual; this keeps the preview glued to the cursor.
|
||||
pub fn solid_f64(name: String, points: Vec<[f64; 3]>, color: [f32; 4], selected: bool) -> Self {
|
||||
let mut hi = Vec::with_capacity(points.len());
|
||||
let mut lo = Vec::with_capacity(points.len());
|
||||
for [x, y, z] in points {
|
||||
let (hx, lx) = Self::split_ds(x);
|
||||
let (hy, ly) = Self::split_ds(y);
|
||||
let (hz, lz) = Self::split_ds(z);
|
||||
hi.push([hx, hy, hz]);
|
||||
lo.push([lx, ly, lz]);
|
||||
}
|
||||
let mut w = Self::solid(name, hi, color, selected);
|
||||
w.points_low = lo;
|
||||
w
|
||||
}
|
||||
|
||||
/// Create a solid wire (no dash pattern, 1px weight).
|
||||
pub fn solid(name: String, points: Vec<[f32; 3]>, color: [f32; 4], selected: bool) -> Self {
|
||||
Self {
|
||||
|
||||
Reference in new issue
Block a user