fix: restore visibility for large-coordinate DXF files after world_offset regression

Three root causes caused all geometry and UCS arrows to disappear:

1. TruckObject::Lines and TruckObject::Text variants returned world-space
   f32 coordinates without applying world_offset, so fit_all() computed
   bounds spanning from local space to UTM world space (~4 M m), placing
   the camera impossibly far from all visible geometry.

2. Ray/XLine entities with unnormalized direction vectors (common in some
   DXF exporters) produced astronomically large far-point coordinates
   (up to 1e28) that overwhelmed the camera fit even after the offset fix.
   Fixed by normalizing the direction vector before multiplying by
   DISPLAY_EXTENT.

3. Origin-stuck corrupted entities (coordinates ≈ 0 in world space become
   ≈ -world_offset in local space) pulled the fit_all() bounds far from
   the actual drawing. Fixed by computing local_extent_max from EXTMIN/EXTMAX
   (10× safety margin) and skipping points outside that range in fit_all().

Additional hardening: wire_gpu.rs now skips ±inf segments (not just NaN),
and snap_pts/key_vertices in all TruckObject variants are offset-corrected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-04-27 18:04:35 +03:00
commit e191315713
4 changed files with 115 additions and 43 deletions

View file

@ -16,10 +16,17 @@ impl TruckConvertible for Ray {
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
let bp = self.base_point;
let dir = self.direction;
// Normalize direction to avoid f32 overflow when DXF stores
// unnormalized direction vectors (garbage data in some exporters).
let len = (dir.x * dir.x + dir.y * dir.y + dir.z * dir.z).sqrt();
if len < 1e-10 {
return None;
}
let (nx, ny, nz) = (dir.x / len, dir.y / len, dir.z / len);
let far = [
(bp.x + dir.x * DISPLAY_EXTENT) as f32,
(bp.y + dir.y * DISPLAY_EXTENT) as f32,
(bp.z + dir.z * DISPLAY_EXTENT) as f32,
(bp.x + nx * DISPLAY_EXTENT) as f32,
(bp.y + ny * DISPLAY_EXTENT) as f32,
(bp.z + nz * DISPLAY_EXTENT) as f32,
];
let start = [bp.x as f32, bp.y as f32, bp.z as f32];
Some(TruckEntity {
@ -138,15 +145,20 @@ impl TruckConvertible for XLine {
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
let bp = self.base_point;
let dir = self.direction;
let len = (dir.x * dir.x + dir.y * dir.y + dir.z * dir.z).sqrt();
if len < 1e-10 {
return None;
}
let (nx, ny, nz) = (dir.x / len, dir.y / len, dir.z / len);
let far_pos = [
(bp.x + dir.x * DISPLAY_EXTENT) as f32,
(bp.y + dir.y * DISPLAY_EXTENT) as f32,
(bp.z + dir.z * DISPLAY_EXTENT) as f32,
(bp.x + nx * DISPLAY_EXTENT) as f32,
(bp.y + ny * DISPLAY_EXTENT) as f32,
(bp.z + nz * DISPLAY_EXTENT) as f32,
];
let far_neg = [
(bp.x - dir.x * DISPLAY_EXTENT) as f32,
(bp.y - dir.y * DISPLAY_EXTENT) as f32,
(bp.z - dir.z * DISPLAY_EXTENT) as f32,
(bp.x - nx * DISPLAY_EXTENT) as f32,
(bp.y - ny * DISPLAY_EXTENT) as f32,
(bp.z - nz * DISPLAY_EXTENT) as f32,
];
Some(TruckEntity {
object: TruckObject::Lines(vec![far_neg, far_pos]),