perf: expand spatial interaction indexing

Share subprimitive broad-phase queries across snap, hover, selection, hatch, and mesh paths while preserving exact hit tests.\n\nRefs #433
This commit is contained in:
Hakan Seven committed 2026-07-24 22:00:40 +03:00
1 parent 4db763ef27
commit 90714d34b2
5 files changed
+2640 -691

No files matched your search

+83 -16
View File
@@ -776,6 +776,7 @@ impl OpenCADStudio {
all_wires,
raw,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
);
@@ -941,6 +942,7 @@ impl OpenCADStudio {
all_wires,
snap_cursor,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
);
@@ -1547,6 +1549,7 @@ impl OpenCADStudio {
all_wires,
raw,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
);
@@ -2034,6 +2037,7 @@ impl OpenCADStudio {
all_wires,
snap_cursor,
view_rot,
eye,
bounds,
self.snapper.osnap_radius_px,
);
@@ -2206,10 +2210,11 @@ impl OpenCADStudio {
.unwrap_or(false)
{
let (view_rot2, eye2, all_wires2) = self.pick_view(i, &edit_cam, bounds);
let click_candidates = self.tabs[i].scene.interaction_candidates_near(
let click_candidates = self.tabs[i].scene.interaction_pick_candidates_near(
all_wires2,
world_pt,
view_rot2,
eye2,
bounds,
scene::pick::hit_test::CLICK_THRESHOLD_PX * 2.0,
);
@@ -2445,9 +2450,14 @@ impl OpenCADStudio {
aabb
},
);
let area_candidates = self.tabs[i]
.scene
.interaction_candidates_in_aabb(all_wires, world_aabb, view_rot);
let area_candidates = self.tabs[i].scene.interaction_candidates_in_aabb(
all_wires,
world_aabb,
[a.x.min(p.x), a.y.min(p.y), a.x.max(p.x), a.y.max(p.y)],
view_rot,
eye,
bounds,
);
let candidate_handles = self.tabs[i]
.scene
.interaction_candidate_handles(&area_candidates);
@@ -2475,6 +2485,16 @@ impl OpenCADStudio {
bounds,
candidate_handles.as_ref(),
));
handles.extend(scene::pick::hit_test::box_hit_insert_hatch(
a,
p,
crossing,
self.tabs[i].scene.insert_hatches_for_click().as_ref(),
view_rot,
eye,
bounds,
candidate_handles.as_ref(),
));
handles.extend(self.tabs[i].scene.mesh_box_hit(
a,
p,
@@ -2548,9 +2568,28 @@ impl OpenCADStudio {
aabb
},
);
let area_candidates = self.tabs[i]
.scene
.interaction_candidates_in_aabb(all_wires, world_aabb, view_rot);
let area_candidates = self.tabs[i].scene.interaction_candidates_in_aabb(
all_wires,
world_aabb,
poly_pts.iter().fold(
[
f32::INFINITY,
f32::INFINITY,
f32::NEG_INFINITY,
f32::NEG_INFINITY,
],
|mut rect, point| {
rect[0] = rect[0].min(point.x);
rect[1] = rect[1].min(point.y);
rect[2] = rect[2].max(point.x);
rect[3] = rect[3].max(point.y);
rect
},
),
view_rot,
eye,
bounds,
);
let candidate_handles = self.tabs[i]
.scene
.interaction_candidate_handles(&area_candidates);
@@ -2576,6 +2615,15 @@ impl OpenCADStudio {
bounds,
candidate_handles.as_ref(),
));
handles.extend(scene::pick::hit_test::poly_hit_insert_hatch(
&poly_pts,
crossing,
self.tabs[i].scene.insert_hatches_for_click().as_ref(),
view_rot,
eye,
bounds,
candidate_handles.as_ref(),
));
handles.extend(self.tabs[i].scene.mesh_poly_hit(
&poly_pts,
crossing,
@@ -2630,10 +2678,11 @@ impl OpenCADStudio {
if box_anchor.is_none() {
let (view_rot, eye, all_wires) = self.pick_view(i, &edit_cam, bounds);
let click_world = self.cursor_model_point(i, &edit_cam, p, bounds);
let click_candidates = self.tabs[i].scene.interaction_candidates_near(
let click_candidates = self.tabs[i].scene.interaction_pick_candidates_near(
all_wires,
click_world,
view_rot,
eye,
bounds,
scene::pick::hit_test::CLICK_THRESHOLD_PX * 2.0,
);
@@ -2695,7 +2744,7 @@ impl OpenCADStudio {
// parent Insert (AutoCAD behaviour).
scene::pick::hit_test::click_hit_insert_hatch(
p,
&self.tabs[i].scene.insert_hatches_for_click()[..],
self.tabs[i].scene.insert_hatches_for_click().as_ref(),
view_rot,
eye,
bounds,
@@ -2801,9 +2850,14 @@ impl OpenCADStudio {
aabb
},
);
let area_candidates = self.tabs[i]
.scene
.interaction_candidates_in_aabb(all_wires, world_aabb, view_rot);
let area_candidates = self.tabs[i].scene.interaction_candidates_in_aabb(
all_wires,
world_aabb,
[a.x.min(p.x), a.y.min(p.y), a.x.max(p.x), a.y.max(p.y)],
view_rot,
eye,
bounds,
);
let candidate_handles = self.tabs[i]
.scene
.interaction_candidate_handles(&area_candidates);
@@ -2831,6 +2885,16 @@ impl OpenCADStudio {
bounds,
candidate_handles.as_ref(),
));
handles.extend(scene::pick::hit_test::box_hit_insert_hatch(
a,
p,
crossing,
self.tabs[i].scene.insert_hatches_for_click().as_ref(),
view_rot,
eye,
bounds,
candidate_handles.as_ref(),
));
handles.extend(self.tabs[i].scene.mesh_box_hit(
a,
p,
@@ -2937,10 +3001,11 @@ impl OpenCADStudio {
};
let all_wires = self.tabs[i].scene.hit_test_wires();
let click_world = self.cursor_model_point(i, &edit_cam, p, bounds);
let click_candidates = self.tabs[i].scene.interaction_candidates_near(
let click_candidates = self.tabs[i].scene.interaction_pick_candidates_near(
all_wires,
click_world,
view_rot,
eye,
bounds,
scene::pick::hit_test::CLICK_THRESHOLD_PX * 2.0,
);
@@ -3058,10 +3123,11 @@ impl OpenCADStudio {
};
let all_wires = self.tabs[i].scene.hit_test_wires();
let click_world = self.cursor_model_point(i, &edit_cam, p, bounds);
let click_candidates = self.tabs[i].scene.interaction_candidates_near(
let click_candidates = self.tabs[i].scene.interaction_pick_candidates_near(
all_wires,
click_world,
view_rot,
eye,
bounds,
scene::pick::hit_test::CLICK_THRESHOLD_PX * 2.0,
);
@@ -3384,10 +3450,11 @@ impl OpenCADStudio {
.map(|(cam, _)| cam);
let (view_rot, eye, all_wires) = self.pick_view(i, &edit_cam, bounds);
let hover_world = self.cursor_model_point(i, &edit_cam, p, bounds);
let hover_candidates = self.tabs[i].scene.interaction_candidates_near(
let hover_candidates = self.tabs[i].scene.interaction_pick_candidates_near(
all_wires,
hover_world,
view_rot,
eye,
bounds,
scene::pick::hit_test::CLICK_THRESHOLD_PX * 2.0,
);
@@ -3421,7 +3488,7 @@ impl OpenCADStudio {
.or_else(|| {
scene::pick::hit_test::click_hit_insert_hatch(
p,
&self.tabs[i].scene.insert_hatches_for_click()[..],
self.tabs[i].scene.insert_hatches_for_click().as_ref(),
view_rot,
eye,
bounds,
+644 -261
View File
File diff suppressed because it is too large. Load diff
+817 -199
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+253 -132
View File
@@ -90,7 +90,7 @@ pub struct OtrackHit {
// ── Snapper ───────────────────────────────────────────────────────────────
use rustc_hash::FxHashSet as HashSet;
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
pub struct Snapper {
/// Global snap on/off toggle. When false, all snapping is bypassed
@@ -926,7 +926,7 @@ impl Snapper {
}
}
}
let allow_pairwise = wires.segments().is_some() || in_range_pts <= MAX_PAIRWISE_POINTS;
let allow_unindexed_pairwise = in_range_pts <= MAX_PAIRWISE_POINTS;
let local_segments = indexed_segments(wires);
let mut try_pt = |world: glam::DVec3, snap_type: SnapType| {
@@ -959,56 +959,87 @@ impl Snapper {
};
// ── Pre-baked snap points (Center, Node, Quadrant, Insertion) ──────
for wire in wires.iter() {
for &(world, hint) in &wire.snap_pts {
let snap_type = match hint {
SnapHint::Center => SnapType::Center,
SnapHint::Node => SnapType::Node,
SnapHint::Quadrant => SnapType::Quadrant,
SnapHint::Insertion => SnapType::Insertion,
SnapHint::Midpoint => SnapType::Midpoint,
let mut try_snap_hint = |world: DVec3, hint: SnapHint| {
let snap_type = match hint {
SnapHint::Center => SnapType::Center,
SnapHint::Node => SnapType::Node,
SnapHint::Quadrant => SnapType::Quadrant,
SnapHint::Insertion => SnapType::Insertion,
SnapHint::Midpoint => SnapType::Midpoint,
};
if self.is_on(snap_type) {
try_pt(world, snap_type);
}
};
if let Some(points) = wires.snap_points() {
for point_ref in points {
let Some(&(world, hint)) = wires
.source_wire(point_ref.wire)
.and_then(|wire| wire.snap_pts.get(point_ref.index as usize))
else {
continue;
};
if self.is_on(snap_type) {
try_pt(world, snap_type);
try_snap_hint(world, hint);
}
} else {
for wire in wires.iter() {
for &(world, hint) in &wire.snap_pts {
try_snap_hint(world, hint);
}
}
}
drop(try_snap_hint);
// ── Endpoint ───────────────────────────────────────────────────────
if self.is_on(SnapType::Endpoint) {
for wire in wires.iter() {
if !wire_in_range(wire) {
continue;
if let Some(vertices) = wires.key_vertices() {
for vertex_ref in vertices {
let Some(&point) = wires
.source_wire(vertex_ref.wire)
.and_then(|wire| wire.key_vertices.get(vertex_ref.index as usize))
else {
continue;
};
try_pt(DVec3::from_array(point), SnapType::Endpoint);
}
if !wire.key_vertices.is_empty() {
// Use explicit vertices (Line, LwPolyline): every vertex is an endpoint.
for &p in &wire.key_vertices {
try_pt(glam::DVec3::new(p[0], p[1], p[2]), SnapType::Endpoint);
}
} else {
// Tessellated curves (Circle, Arc, Ellipse): only an OPEN
// one (an arc) has real endpoints. A full circle / ellipse is
// closed — its tessellation's first/last is a seam point, not
// an endpoint — and is the only tessellated curve that carries
// Quadrant snap hints (arcs never do), so emit no Endpoint for
// those (#275).
// Tessellated open curves have no key-vertex set. Their only
// endpoints are first/last, so testing candidate wires remains
// O(local wires), independent of tessellation density.
for wire in wires.iter().filter(|wire| wire.key_vertices.is_empty()) {
let closed = wire
.snap_pts
.iter()
.any(|(_, h)| matches!(h, SnapHint::Quadrant));
if !closed {
if let Some(&p) = wire.points.first() {
try_pt(
glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64),
SnapType::Endpoint,
);
.any(|(_, hint)| matches!(hint, SnapHint::Quadrant));
if closed {
continue;
}
if !wire.points.is_empty() {
try_pt(wp_f64(wire, 0), SnapType::Endpoint);
}
if wire.points.len() > 1 {
try_pt(wp_f64(wire, wire.points.len() - 1), SnapType::Endpoint);
}
}
} else {
for wire in wires.iter() {
if !wire_in_range(wire) {
continue;
}
if !wire.key_vertices.is_empty() {
for &point in &wire.key_vertices {
try_pt(DVec3::from_array(point), SnapType::Endpoint);
}
if wire.points.len() > 1 {
if let Some(&p) = wire.points.last() {
try_pt(
glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64),
SnapType::Endpoint,
);
} else {
let closed = wire
.snap_pts
.iter()
.any(|(_, hint)| matches!(hint, SnapHint::Quadrant));
if !closed {
if !wire.points.is_empty() {
try_pt(wp_f64(wire, 0), SnapType::Endpoint);
}
if wire.points.len() > 1 {
try_pt(wp_f64(wire, wire.points.len() - 1), SnapType::Endpoint);
}
}
}
@@ -1017,20 +1048,32 @@ impl Snapper {
}
// ── Midpoint ───────────────────────────────────────────────────────
// Only explicit vertex sets (Line, LwPolyline) contribute per-segment
// midpoints. Tessellated curves (Circle, Arc, Ellipse, Spline) emit a
// single `SnapHint::Midpoint` snap_pt where one exists — iterating
// every chord here would otherwise turn a circle's tessellation into
// a haze of false midpoint hits. See #34.
// Tessellated curves contribute their pre-baked Midpoint above.
if self.is_on(SnapType::Midpoint) {
for wire in wires.iter() {
if !wire_in_range(wire) {
continue;
if let Some(segments) = wires.key_segments() {
for segment_ref in segments {
let Some(wire) = wires.source_wire(segment_ref.wire) else {
continue;
};
let start = segment_ref.start as usize;
let Some((&a, &b)) = wire
.key_vertices
.get(start)
.zip(wire.key_vertices.get(start + 1))
else {
continue;
};
let a = DVec3::from_array(a);
let b = DVec3::from_array(b);
if a.distance_squared(b) > 1e-12 {
try_pt((a + b) * 0.5, SnapType::Midpoint);
}
}
if !wire.key_vertices.is_empty() {
for seg in wire.key_vertices.windows(2) {
let a = glam::DVec3::new(seg[0][0], seg[0][1], seg[0][2]);
let b = glam::DVec3::new(seg[1][0], seg[1][1], seg[1][2]);
} else {
for wire in wires.iter().filter(|wire| wire_in_range(wire)) {
for segment in wire.key_vertices.windows(2) {
let a = DVec3::from_array(segment[0]);
let b = DVec3::from_array(segment[1]);
if a.distance_squared(b) > 1e-12 {
try_pt((a + b) * 0.5, SnapType::Midpoint);
}
@@ -1095,30 +1138,35 @@ impl Snapper {
}
// ── Intersection — segment-segment intersections (pairwise, gated) ──
if self.is_on(SnapType::Intersection) && allow_pairwise {
if self.is_on(SnapType::Intersection)
&& (local_segments.is_some() || allow_unindexed_pairwise)
{
if let Some(segments) = &local_segments {
// Cursor-local segment bounds make this set small. In a
// pathological dense crossing retain closest segments instead
// of disabling Intersection for the whole aperture.
const MAX_LOCAL_INTERSECTION_SEGMENTS: usize = 512;
// Exact cursor-local sweep: never discard a valid intersection
// in dense geometry. Min-X ordering plus Y overlap avoids
// comparing segment pairs whose bounds cannot meet.
let mut local: Vec<&IndexedSegment> = segments.iter().collect();
local.sort_by(|a, b| {
segment_aabb_distance2(a, cursor_world)
.total_cmp(&segment_aabb_distance2(b, cursor_world))
});
local.truncate(MAX_LOCAL_INTERSECTION_SEGMENTS);
local.sort_by(|a, b| a.min_x().total_cmp(&b.min_x()));
for i in 0..local.len() {
let a = local[i];
for &b in local.iter().skip(i + 1) {
if b.min_x() > a.max_x() {
break;
}
if a.wire == b.wire || a.max_y() < b.min_y() || a.min_y() > b.max_y() {
continue;
}
if let Some(pt) = seg_intersect_3d(a.a, a.b, b.a, b.b) {
try_pt(pt, SnapType::Intersection);
if indexed_sweep_within_budget(&local) {
'intersection_sweep: for i in 0..local.len() {
let a = local[i];
for &b in local.iter().skip(i + 1) {
if b.min_x() > a.max_x() {
break;
}
if a.wire == b.wire || a.max_y() < b.min_y() || a.min_y() > b.max_y() {
continue;
}
if let Some(pt) = seg_intersect_3d(a.a, a.b, b.a, b.b) {
let exact_cursor = dist2(
world_to_screen(pt, view_rot, eye, bounds),
cursor_screen,
) <= f32::EPSILON;
try_pt(pt, SnapType::Intersection);
if exact_cursor {
break 'intersection_sweep;
}
}
}
}
}
@@ -1237,39 +1285,57 @@ impl Snapper {
// ── Apparent Intersection — screen-space intersections (pairwise, gated) ──
// L: pre-project each in-range wire's points to screen once, not once per segment pair.
if self.is_on(SnapType::ApparentIntersection) && allow_pairwise {
if self.is_on(SnapType::ApparentIntersection)
&& (local_segments.is_some() || allow_unindexed_pairwise)
{
if let Some(segments) = &local_segments {
const MAX_LOCAL_APPARENT_SEGMENTS: usize = 512;
let mut local: Vec<&IndexedSegment> = segments.iter().collect();
local.sort_by(|a, b| {
segment_aabb_distance2(a, cursor_world)
.total_cmp(&segment_aabb_distance2(b, cursor_world))
});
local.truncate(MAX_LOCAL_APPARENT_SEGMENTS);
let projected: Vec<(Point, Point)> = local
// Project once, then run an exact screen-AABB sweep. Unlike the
// previous 512-item cap this cannot drop the true apparent
// intersection in a dense aperture.
let mut projected: Vec<(&IndexedSegment, Point, Point, [f32; 4])> = segments
.iter()
.map(|seg| {
let a = world_to_screen(seg.a, view_rot, eye, bounds);
let b = world_to_screen(seg.b, view_rot, eye, bounds);
(
world_to_screen(seg.a, view_rot, eye, bounds),
world_to_screen(seg.b, view_rot, eye, bounds),
seg,
a,
b,
[a.x.min(b.x), a.y.min(b.y), a.x.max(b.x), a.y.max(b.y)],
)
})
.collect();
for i in 0..local.len() {
for j in (i + 1)..local.len() {
if local[i].wire == local[j].wire {
continue;
}
if let Some((ta, _)) = seg_intersect_2d(
projected[i].0,
projected[i].1,
projected[j].0,
projected[j].1,
) {
try_pt(
local[i].a + ta as f64 * (local[i].b - local[i].a),
SnapType::ApparentIntersection,
);
projected.sort_by(|a, b| a.3[0].total_cmp(&b.3[0]));
if projected_sweep_within_budget(&projected) {
'apparent_sweep: for i in 0..projected.len() {
let (segment_a, screen_a0, screen_a1, aabb_a) = projected[i];
for &(segment_b, screen_b0, screen_b1, aabb_b) in
projected.iter().skip(i + 1)
{
if aabb_b[0] > aabb_a[2] {
break;
}
if segment_a.wire == segment_b.wire
|| aabb_a[3] < aabb_b[1]
|| aabb_a[1] > aabb_b[3]
{
continue;
}
if let Some((ta, _)) =
seg_intersect_2d(screen_a0, screen_a1, screen_b0, screen_b1)
{
let apparent_screen = Point::new(
screen_a0.x + ta * (screen_a1.x - screen_a0.x),
screen_a0.y + ta * (screen_a1.y - screen_a0.y),
);
try_pt(
segment_a.a + ta as f64 * (segment_a.b - segment_a.a),
SnapType::ApparentIntersection,
);
if dist2(apparent_screen, cursor_screen) <= f32::EPSILON {
break 'apparent_sweep;
}
}
}
}
}
@@ -1450,27 +1516,15 @@ impl Snapper {
// the cursor is to the curve. Runs here, after `try_pt`'s borrow ends,
// so it can update the candidate state directly. (#152)
if self.is_on(SnapType::Center) {
for wire in wires.iter() {
if !wire_in_range(wire) {
continue;
}
// Only tessellated curves carry a pre-baked Center hint; reuse
// it as the snap target. Lines / polylines have none → skip.
let mut offer = |wire: &WireModel, curve_d2: f32| {
let Some(center) = wire
.snap_pts
.iter()
.find(|(_, h)| matches!(h, SnapHint::Center))
.find(|(_, hint)| matches!(hint, SnapHint::Center))
.map(|&(c, _)| c)
else {
continue;
return;
};
// Nearest screen distance from the cursor to the curve itself.
let mut curve_d2 = f32::INFINITY;
for i in 0..wire.points.len().saturating_sub(1) {
let p = nearest_on_segment(cursor_world, wp_f64(wire, i), wp_f64(wire, i + 1));
let sp = world_to_screen(p, view_rot, eye, bounds);
curve_d2 = curve_d2.min(dist2(sp, cursor_screen));
}
let screen = world_to_screen(center, view_rot, eye, bounds);
// Rim-hover Center: the cursor is on the CURVE, not near the
// centre, so its distance metric (curve_d2 ≈ 0 anywhere on the
@@ -1496,6 +1550,51 @@ impl Snapper {
extension_base2: None,
});
}
};
if let Some(segments) = &local_segments {
let mut distances: HashMap<u32, f32> = HashMap::default();
for segment in segments {
let Some(wire) = wires.source_wire(segment.wire) else {
continue;
};
if !wire
.snap_pts
.iter()
.any(|(_, hint)| matches!(hint, SnapHint::Center))
{
continue;
}
let nearest = nearest_on_segment(cursor_world, segment.a, segment.b);
let distance = dist2(
world_to_screen(nearest, view_rot, eye, bounds),
cursor_screen,
);
distances
.entry(segment.wire)
.and_modify(|best| *best = best.min(distance))
.or_insert(distance);
}
for (wire_idx, distance) in distances {
if let Some(wire) = wires.source_wire(wire_idx) {
offer(wire, distance);
}
}
} else {
for wire in wires.iter().filter(|wire| wire_in_range(wire)) {
let mut curve_d2 = f32::INFINITY;
for index in 0..wire.points.len().saturating_sub(1) {
let nearest = nearest_on_segment(
cursor_world,
wp_f64(wire, index),
wp_f64(wire, index + 1),
);
curve_d2 = curve_d2.min(dist2(
world_to_screen(nearest, view_rot, eye, bounds),
cursor_screen,
));
}
offer(wire, curve_d2);
}
}
}
@@ -1683,6 +1782,46 @@ impl IndexedSegment {
}
}
const MAX_INDEXED_PAIRWISE_WORK: usize = 500_000;
fn indexed_sweep_within_budget(segments: &[&IndexedSegment]) -> bool {
let mut work = 0usize;
for (index, &a) in segments.iter().enumerate() {
for &b in segments.iter().skip(index + 1) {
if b.min_x() > a.max_x() {
break;
}
work += 1;
if work > MAX_INDEXED_PAIRWISE_WORK {
return false;
}
if a.wire == b.wire || a.max_y() < b.min_y() || a.min_y() > b.max_y() {
continue;
}
}
}
true
}
fn projected_sweep_within_budget(segments: &[(&IndexedSegment, Point, Point, [f32; 4])]) -> bool {
let mut work = 0usize;
for (index, &(a, _, _, aabb_a)) in segments.iter().enumerate() {
for &(b, _, _, aabb_b) in segments.iter().skip(index + 1) {
if aabb_b[0] > aabb_a[2] {
break;
}
work += 1;
if work > MAX_INDEXED_PAIRWISE_WORK {
return false;
}
if a.wire == b.wire || aabb_a[3] < aabb_b[1] || aabb_a[1] > aabb_b[3] {
continue;
}
}
}
true
}
fn indexed_segments<W: WireSource + ?Sized>(wires: &W) -> Option<Vec<IndexedSegment>> {
let refs = wires.segments()?;
Some(
@@ -1706,24 +1845,6 @@ fn indexed_segments<W: WireSource + ?Sized>(wires: &W) -> Option<Vec<IndexedSegm
)
}
fn segment_aabb_distance2(segment: &IndexedSegment, point: DVec3) -> f64 {
let dx = if point.x < segment.min_x() {
segment.min_x() - point.x
} else if point.x > segment.max_x() {
point.x - segment.max_x()
} else {
0.0
};
let dy = if point.y < segment.min_y() {
segment.min_y() - point.y
} else if point.y > segment.max_y() {
point.y - segment.max_y()
} else {
0.0
};
dx * dx + dy * dy
}
/// Reconstruct the absolute f64 position of wire vertex `i` from its
/// double-single high/low pair. At UTM-scale coordinates the `points` (high)
/// f32 alone is ~0.5 m off; adding the low residual restores f64 precision so