fix(xclip): precise clip + carry clip across cross-drawing paste

Clipped blocks were broken at UTM and lost their clip when pasted into
another drawing.

- Clip geometry: world_clip_polygon_f64 keeps the boundary in absolute f64;
  clip_wires now clips in a frame relative to the boundary's first vertex
  (small coords → exact f32 Sutherland–Hodgman) and re-splits the result
  into the double-single high/low pair the relative-to-eye renderer needs,
  so the clipped block draws correctly and no longer poisons ZOOM Extents.
- ZOOM Extents (fit_all): the outlier reject compared absolute UTM
  coordinates against a centre-RELATIVE span (local_extent_max), rejecting
  the whole drawing → no-op. Made the reject distance-from-median-centre.
- Cross-drawing paste: clipboard now snapshots each copied entity's whole
  xdictionary object graph (ClipboardDeps.ext_objects) and recreates it on
  paste with fresh handles + remapped references, re-pointing the pasted
  entity's xdictionary at the new root. Wired into PASTECLIP and PASTEORIG.
  Fixed handle allocation (allocate_handle, not the non-advancing
  next_handle) so the dictionary chain doesn't collapse onto one handle.
- Updated hit_test / plugin_host tests for the eye-relative + DVec3 signatures.

Known gaps: PASTEBLOCK does not yet carry the clip (clip would need to live
inside the new wrapper block definition); hatch-clip path still f32.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-24 09:33:55 +03:00
commit 6667042372
7 changed files with 330 additions and 26 deletions

View file

@ -631,9 +631,16 @@ impl OpenCADStudio {
// else a block reference renders empty in a drawing that
// lacks the definition. (#135 / #158)
self.merge_clipboard_blocks(i);
for entity in self.clipboard.clone() {
self.tabs[i].scene.add_entity_clone(entity);
}
let by_index: Vec<acadrust::Handle> = self
.clipboard
.clone()
.into_iter()
.map(|entity| self.tabs[i].scene.add_entity_clone(entity))
.collect();
// Recreate each pasted entity's xdictionary graph (XCLIP
// spatial filters etc.) so a cross-drawing paste keeps its
// clip instead of showing the whole block. (#xclip-paste)
self.merge_clipboard_ext_objects(i, &by_index);
// Tessellate any pasted ACIS solids (top-level + inside a
// recreated block) so they render instead of staying blank.
self.tabs[i].scene.populate_meshes_from_document();