Three changes to make paper-space viewports render correctly on
UTM-scale drawings whose viewports were saved with default
view_target=(0, 0, 0) and a view_center pointing at empty WCS:
1. **Auto-fit fallback.** When the saved view's WCS rect doesn't
overlap the IQR-bounded content cluster (`world_offset ±
local_extent_max`), override `view_center` with `world_offset` and
recompute `view_height` to fit the cluster into the paper viewport.
Matches AutoCAD's silent auto-fit-on-open for stale / uninitialized
viewports; without it those viewports rendered blank.
2. **f64 projection inner loop.** The previous f32 path computed
`(wire_offset_rel - target_offset_rel).dot(view_right) -
view_center` by subtracting values at ~5e6 magnitude (f32 ULP
~0.5 m) to land on a small paper offset. The cancellation produced
centimetre-scale jitter on paper output even when the model was
clean. Reconstruct the wire WCS coord, subtract the display center,
and dot-project in f64; cast to f32 only at the final paper
position where magnitudes are bounded by the viewport rect.
3. **examples/inspect_viewports.rs** — diagnostic that dumps every
viewport's saved view fields (view_target, view_center, view_height
vs paper height, custom_scale, status flags) plus drawing-level
insertion_units and model-space extents. Used to verify that
acadrust's DWG reader reads view_height correctly; the
`view_height == vp.height` patterns observed on real files turn out
to be genuine "default 1:1" file content rather than a reader bug
(a round-trip test through DwgWriter / DwgReader survives all
per-viewport values).
Also: switch the `acadrust` patch from `HakanSeven12/acadrust@feat/
expose-blockrecord-is-loaded` (a stale branch with the abandoned
is_loaded experiment) to `hakanaktt/acadrust@main`. Upstream main
now carries the layout paper-dimensions and mirrored-arc fixes that
this branch used to add — plus PR #20's DXF reading fixes that the
old branch was missing.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Block defns and top-level entities now know their world-space XY
AABB, and `tessellate_entity` / `expand_insert` early-out for anything
that doesn't intersect the camera's view rect. Tested commit-only on
time_open (correct subset emitted with default camera); GUI run
pending user verification.
Cache plumbing:
- `LocalWire` / `BlockDefn` carry `aabb_local` (post-build recursive
union over nested defns).
- `Scene::view_world_aabb()` derives a 25%-margined world rect from
the active camera + last-seen render aspect.
- `wire_cache` / `paper_sheet_cache` keys widen to
`(geometry_epoch, camera_generation)` so pan/zoom invalidates the
cached wire list — and pipeline `cached_epoch` widens to match
so the GPU re-uploads on view change.
- `XrefStatus::Unloaded` ack already shipped — orthogonal to this.
Also adds `examples/xref_states.rs` to dump per-block_record xref
metadata for diagnosing the is_loaded / unloaded distinction.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Examples can't import from a bin-only crate, so add a thin lib.rs that
re-exports the existing modules. Used by the new examples that helped
diagnose the freeze fixed in the previous commit.
- examples/time_open: times parse / purge / cache / first-wires phases
- examples/inspect_insert: lists Insert blocks with sub-entity counts
- examples/find_raster: dumps RasterImage path + dimensions
Co-Authored-By: Claude Opus 4.7 <[email protected]>
acadrust's DWG reader occasionally desynchronises on certain files
(observed on render.dwg: 1519 of 1763 LwPolylines arrived with non-unit
normals in the 1e200+ range and 100k phantom vertices). Tessellating
those entities allocates gigabytes and produces NaN-laden wires,
freezing the UI.
Add a pre-tessellation guard that scans freshly loaded documents and
drops any entity failing a cheap sanity check: non-unit normal,
non-finite or absurd coordinate, or vertex count above 100k. Count of
dropped entities is threaded through DerivedCaches and surfaced as a
warning in the command line so the user knows the file was patched up
on the way in.
Same file in DXF form parses cleanly (0 corrupt), so this is strictly
a DWG-path workaround until the upstream parser bug is fixed.
The new examples/inspect_polyline.rs is a one-off diagnostic that dumps
LwPolyline/Polyline2D/Polyline3D fields plus a corrupt-entity count;
useful for narrowing down the acadrust bug.
Co-Authored-By: Claude Opus 4.7 <[email protected]>