forked from 1b-agent/opencadstudio-upstream
fix(annotative): start new drawings at the unit-aware annotation scale
A new drawing is metric with metre insertion units, but its annotation multiplier stayed at Scene::new()'s unitless 1 while opened files and CANNOSCALE convert paper millimetres into drawing units (0.001 at 1:1). Annotative text and dimensions were drawn 1000x too large until the first scale change, then shrank to their real size and looked gone, also after switching back to 1:1. One helper now derives the multiplier from the header; new drawings, file open and every INSUNITS change (UNITS, the units popup, DWGUNITS, SETVAR) go through it. Fixes #1674 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
85627ebc8a
commit
5d0390bcdf
6 files changed
+31
-31
No files matched your search
@@ -893,6 +893,7 @@ impl OpenCADStudio {
|
||||
|
||||
self.push_undo_snapshot(i, "DWGUNITS");
|
||||
self.tabs[i].scene.document.header.insertion_units = to;
|
||||
self.tabs[i].scene.sync_annotation_scale_from_header();
|
||||
|
||||
let factor = units::conversion_factor(from, to).filter(|f| (f - 1.0).abs() > 1e-12);
|
||||
let (from_label, to_label) = (units::label(from), units::label(to));
|
||||
|
||||
@@ -3088,6 +3088,10 @@ impl OpenCADStudio {
|
||||
self.delete_objects = value;
|
||||
}
|
||||
if changed {
|
||||
if name == "INSUNITS" {
|
||||
self.tabs[i].scene.sync_annotation_scale_from_header();
|
||||
self.tabs[i].scene.invalidate_annotation_dependencies();
|
||||
}
|
||||
if matches!(
|
||||
name.as_str(),
|
||||
"ZOOMWHEEL"
|
||||
|
||||
+1
-16
@@ -2115,22 +2115,7 @@ impl OpenCADStudio {
|
||||
) {
|
||||
crate::scene::text::ttf_glyph::clear_fallback_cache();
|
||||
}
|
||||
// Current model-space annotation scale comes from the drawing's
|
||||
// CANNOSCALEVALUE (paper/drawing factor). Convert its inverse into
|
||||
// drawing units as well: metric annotation sizes are paper millimetres
|
||||
// and imperial annotation sizes are paper inches.
|
||||
// Current model-space annotation scale comes from the drawing's
|
||||
// CANNOSCALEVALUE (paper/drawing factor). Convert its paper unit into
|
||||
// the drawing's INSUNITS as well, so e.g. a metre drawing uses
|
||||
// 0.001 model units for 1 mm of paper at 1:1.
|
||||
let cannoscale_value = self.tabs[i].scene.document.header.annotation_scale_value;
|
||||
let unit_factor = self.tabs[i].scene.annotation_scale_unit_factor();
|
||||
|
||||
self.tabs[i].scene.annotation_scale = if cannoscale_value > 1e-9 {
|
||||
((1.0 / cannoscale_value) / unit_factor) as f32
|
||||
} else {
|
||||
(1.0 / unit_factor) as f32
|
||||
};
|
||||
self.tabs[i].scene.sync_annotation_scale_from_header();
|
||||
|
||||
// Open-time breakdown so regressions are visible immediately.
|
||||
// `total` is wall time from the Open click to here (post-xref,
|
||||
|
||||
@@ -5442,6 +5442,8 @@ impl OpenCADStudio {
|
||||
header.angle_base = degrees.to_radians();
|
||||
}
|
||||
header.insertion_units = state.insertion_units;
|
||||
self.tabs[i].scene.sync_annotation_scale_from_header();
|
||||
self.tabs[i].scene.invalidate_annotation_dependencies();
|
||||
self.tabs[i].dirty = true;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.refresh_properties();
|
||||
@@ -6020,6 +6022,8 @@ impl OpenCADStudio {
|
||||
// menu having done nothing. (#668)
|
||||
self.push_undo_snapshot(i, "UNITS");
|
||||
self.tabs[i].scene.document.header.insertion_units = code;
|
||||
self.tabs[i].scene.sync_annotation_scale_from_header();
|
||||
self.tabs[i].scene.invalidate_annotation_dependencies();
|
||||
self.tabs[i].dirty = true;
|
||||
let label = crate::modules::draw::units::label(code);
|
||||
self.command_line.push_output(
|
||||
|
||||
@@ -3090,6 +3090,10 @@ impl Scene {
|
||||
// The name alone leaves the header pointing at the previous style, and
|
||||
// a DWG writes the current style by handle only.
|
||||
self.document.header.current_dimstyle_handle = iso;
|
||||
// The annotation multiplier depends on those units; Scene::new()
|
||||
// left it at the unitless 1, which drew annotative objects 1000x too
|
||||
// large until the first CANNOSCALE change shrank them. (#1674)
|
||||
self.sync_annotation_scale_from_header();
|
||||
for obj in self.document.objects.values_mut() {
|
||||
if let codec::objects::ObjectType::Layout(l) = obj {
|
||||
if l.name != "Model" {
|
||||
|
||||
+17
-15
@@ -1448,14 +1448,7 @@ pub fn prepare_open_geometry(
|
||||
scene.local_extent_max = caches.local_extent_max;
|
||||
scene.local_center = caches.local_center;
|
||||
scene.bg_color = model_bg;
|
||||
let cannoscale_value = scene.document.header.annotation_scale_value;
|
||||
let unit_factor = scene.annotation_scale_unit_factor();
|
||||
|
||||
scene.annotation_scale = if cannoscale_value > 1e-9 {
|
||||
((1.0 / cannoscale_value) / unit_factor) as f32
|
||||
} else {
|
||||
(1.0 / unit_factor) as f32
|
||||
};
|
||||
scene.sync_annotation_scale_from_header();
|
||||
scene.current_layout = "Model".to_string();
|
||||
let camera = scene.camera.borrow().clone();
|
||||
let perf = crate::perf::enabled();
|
||||
@@ -5373,6 +5366,21 @@ impl Scene {
|
||||
/// The built-in scale factors are defined assuming model and paper use
|
||||
/// the same base unit. A drawing in metres therefore needs an extra
|
||||
/// factor of 1000 when its paper side is measured in millimetres.
|
||||
/// Model-space annotation multiplier from the header's CANNOSCALEVALUE
|
||||
/// (paper/drawing factor), converted from paper units into the drawing's
|
||||
/// INSUNITS, so a metre drawing uses 0.001 model units per paper
|
||||
/// millimetre at 1:1. Every path that starts or loads a drawing, or
|
||||
/// changes its units, goes through here so it agrees with CANNOSCALE.
|
||||
pub(crate) fn sync_annotation_scale_from_header(&mut self) {
|
||||
let cannoscale_value = self.document.header.annotation_scale_value;
|
||||
let unit_factor = self.annotation_scale_unit_factor();
|
||||
self.annotation_scale = if cannoscale_value > 1e-9 {
|
||||
((1.0 / cannoscale_value) / unit_factor) as f32
|
||||
} else {
|
||||
(1.0 / unit_factor) as f32
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn annotation_scale_unit_factor(&self) -> f64 {
|
||||
let paper_unit = if self.prefers_imperial_scales() == Some(true) {
|
||||
1 // Inches
|
||||
@@ -13384,13 +13392,7 @@ mod journal_tests {
|
||||
scene.local_center = caches.local_center;
|
||||
scene.bg_color = model_bg;
|
||||
scene.current_layout = "Model".to_string();
|
||||
let scale = scene.document.header.annotation_scale_value;
|
||||
let unit_factor = scene.annotation_scale_unit_factor();
|
||||
scene.annotation_scale = if scale > 1e-9 {
|
||||
((1.0 / scale) / unit_factor) as f32
|
||||
} else {
|
||||
(1.0 / unit_factor) as f32
|
||||
};
|
||||
scene.sync_annotation_scale_from_header();
|
||||
scene.install_prepared_open_geometry(prepared);
|
||||
|
||||
let hits = scene.resident_patch_hits.get();
|
||||
|
||||
Reference in new issue
Block a user