forked from 1b-agent/opencadstudio-upstream
Use viewport snap frame and accepted snaps for dimension measurement
Removes PR2's two seams now that PR1 (viewport snapping) is underneath.
* `Scene::viewport_frame` is PR1's camera-derived implementation. The
viewport-record version is gone; PR1's returns `None` for oblique /
perspective viewports, which is what we want — every entry point in
`viewport_dim_seam` then declines rather than guessing a planar
mapping. `viewport_dim_seam` is now just the dimension object-pick
path, and its module doc says so.
* There is one accepted-snap store: PR1's `OpenCADStudio::accepted_snaps`.
PR2's parallel `dim_accepted_snaps` (and its command-name ownership
tracking, which PR1's clear-on-command-start/end already does) is
deleted, along with the `record_dimension_accepted_snap` seam.
`accepted_snap_for_point` reads PR1's list.
Two things layer on top:
- the explicit object pick is not a point step, so it still records its
own snaps, now through `push_accepted_snap` into PR1's list, and now
carrying the picked entity handle + block path as a `SnapSourceRef`
so PR3 can associate it;
- a typed coordinate carries no snap, so `measure_snap` re-attaches the
content viewport under a snap that is free *and* source-less. That
keeps `DIMLINEAR` with typed coordinates inside a 1:10 viewport
measuring the model, without ever reinterpreting a real paper-sheet
snap that happens to sit over a viewport.
* One association gate, not two. `dimension_association_allowed` is the
single predicate, derived from the same `dimension_measure_space`
classification that decides whether to compensate the measurement, so
the two can never disagree. `infer_dimension_sources_guarded` delegates
to it, and the commit path's "commit unassociated when measured through
a viewport" condition is now that predicate rather than a second,
independently-computed bool. It also covers the explicit-pick and
explicit-source-list branches, which the old inference-only guard did
not. Because the classification ignores the trailing dimension-line
placement click, an ordinary paper dimension whose placement click lands
inside a viewport rectangle keeps its association.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
848f789018
commit
43dea41498
5 files changed
+170
-177
No files matched your search
@@ -1,19 +1,20 @@
|
||||
//! PR2 seams onto the paper-space viewport world.
|
||||
//! Object-pick resolution for paper-space dimensions taken through a layout
|
||||
//! viewport.
|
||||
//!
|
||||
//! Everything in this file exists so that viewport-aware dimension
|
||||
//! measurement works *without* PR1 (viewport snapping) in the tree. Each seam
|
||||
//! is small and self-contained; the merge notes say which ones PR1 replaces.
|
||||
//! Paper-space hit testing only sees the sheet's own entities, so a dimension
|
||||
//! command's explicit "select object" pick that lands inside a content
|
||||
//! viewport finds nothing. [`Scene::dimension_pick_through_viewport`] maps the
|
||||
//! click into model space through the viewport's
|
||||
//! [`crate::scene::viewport_ref::ViewportFrame`], hit-tests the viewport's
|
||||
//! resident model wires (descending into block instances and baking the
|
||||
//! instance transform), and hands back a copy of the picked entity already
|
||||
//! projected onto the sheet.
|
||||
//!
|
||||
//! ## Seams
|
||||
//! * [`Scene::viewport_frame`] — **replaced by PR1.** PR1 owns construction of
|
||||
//! [`ViewportFrame`] from the live viewport camera. This implementation
|
||||
//! derives the frame straight from the DXF viewport record, which is correct
|
||||
//! for plan (non-oblique) content viewports.
|
||||
//! * [`Scene::content_viewport_at_paper_point`] /
|
||||
//! [`Scene::viewport_frame_at_paper_point`] — PR1 supersedes these with its
|
||||
//! snap-time viewport resolution; harmless to keep.
|
||||
//! * [`Scene::dimension_pick_through_viewport`] — PR2 owns this permanently.
|
||||
//! It is the explicit-object-pick path and does not depend on PR1.
|
||||
//! The frame itself is built by [`Scene::viewport_frame`] (see
|
||||
//! `crate::scene::mspace`), which derives it from the *live viewport camera*
|
||||
//! so it always agrees with the pixels the renderer drew. It returns `None`
|
||||
//! for oblique / perspective viewports, and every entry point here then
|
||||
//! declines the pick rather than guessing a planar mapping.
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -43,33 +44,6 @@ pub struct ViewportDimPick {
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
// ───────────────────────── PR1 SEAM: BEGIN ──────────────────────────
|
||||
// Replace the body of `viewport_frame` with PR1's implementation on
|
||||
// merge; the signature is the shared contract and must not change.
|
||||
|
||||
/// Planar paper↔model mapping for one layout viewport.
|
||||
///
|
||||
/// Derived from the viewport record rather than the render camera:
|
||||
/// `paper_center = vp.center`, `model_target = vp.view_target`,
|
||||
/// `scale = vp_effective_scale(...)`, `twist = vp.twist_angle`.
|
||||
pub fn viewport_frame(&self, viewport: Handle) -> Option<ViewportFrame> {
|
||||
let Some(EntityType::Viewport(vp)) = self.document.get_entity(viewport) else {
|
||||
return None;
|
||||
};
|
||||
let scale = vp_effective_scale(vp.custom_scale, vp.view_height, vp.height);
|
||||
if !scale.is_finite() || scale.abs() < 1e-12 {
|
||||
return None;
|
||||
}
|
||||
Some(ViewportFrame {
|
||||
viewport,
|
||||
paper_center: DVec2::new(vp.center.x, vp.center.y),
|
||||
model_target: DVec2::new(vp.view_target.x, vp.view_target.y),
|
||||
scale,
|
||||
twist: vp.twist_angle,
|
||||
locked: vp.status.locked,
|
||||
})
|
||||
}
|
||||
// ────────────────────────── PR1 SEAM: END ───────────────────────────
|
||||
|
||||
/// The smallest *on* content viewport of the current layout whose paper
|
||||
/// rectangle contains `paper`. `None` on the Model tab, while editing
|
||||
|
||||
Reference in new issue
Block a user