Resolve dimension object picks against model geometry inside a viewport

Paper-space hit testing only sees sheet entities, so DIMLINEAR / DIMALIGNED /
DIMRADIUS / DIMDIAMETER / DIMANGULAR in "select object" mode found nothing
when the user clicked the model geometry a viewport displays.

A pick that lands inside a content viewport is now mapped into model space
through the viewport frame and tested against that viewport's resident model
wires - the same tessellation it draws, so the pick matches what the user
sees. Ordinary block instances are descended into, with the instance
transform (recursively, up to eight levels) baked into the extracted
geometry, so a line inside a block measures its placed length.

The picked entity is handed to the command already projected onto the sheet,
so all five commands keep working entirely in paper coordinates and unchanged;
the pick is recorded as a viewport snap, so the committed dimension is
compensated exactly like a point-input one. A miss falls through to the
ordinary paper-space pick.

Also narrows mixed-space classification to the measuring points: the final
click of each of these commands is the dimension-line placement, which lands
on bare sheet for viewport measurements and inside a viewport rectangle for
paper ones, and says nothing about what is being measured.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Christopher OverbeckandClaude Fable 5.1 committed 2026-09-15 12:40:44 -05:00
1 parent 30c5ccbba1
commit fcf1b96fdf
2 files changed
+70 -35

No files matched your search

+23 -1
View File
@@ -3824,7 +3824,29 @@ impl OpenCADStudio {
command.set_ctrl(self.ctrl_down);
command.set_shift(self.shift_down);
}
let result = if self.tabs[i]
// PR2: a dimension "select object" pick that lands inside a paper
// content viewport is resolved against the model geometry that
// viewport displays. Paper hit testing only sees sheet entities,
// so this runs first and falls through when it finds nothing.
let dimension_viewport_pick = if self.tabs[i].active_cmd.as_ref().is_some_and(
|command| command.needs_entity_pick() && command.measures_through_viewports(),
) {
let aperture_paper = {
let camera = self.tabs[i].scene.camera.borrow();
let per_px = if bounds.height > 0.0 {
camera.ortho_size() as f64 * 2.0 / bounds.height as f64
} else {
0.0
};
crate::ui::overlay::pick_box_aperture_px(self.pick_box) as f64 * per_px
};
self.try_dimension_viewport_entity_pick(i, pick_wcs, aperture_paper)
} else {
None
};
let result = if let Some(result) = dimension_viewport_pick {
Some(result)
} else if self.tabs[i]
.active_cmd
.as_ref()
.map(|c| c.needs_structure_point_pick())