forked from 1b-agent/opencadstudio-upstream
fix(render): annotative scale representations + model-space linetype scale
Two rendering defects surfaced on the budweiser benchmark drawings, both tied to a drawing's annotation scale. Annotative scale representations. A drawing may materialise each annotation scale as its own object (here a block insert per scale, on a "0 @ <scale>" layer, each carrying a per-object AcDbContextData bound to one scale). Nothing filtered them, so every scale drew at once — a 1× copy stacked under a 10× one. Add annotative::annotative_offscale and apply it in the three paths that expand block content: the wire block-defn cache, the resident/top-level visibility gate (model space only — paper viewports use their per-viewport frozen scale layers), and the exploded-insert hatch/fill walk (filtered before normalize strips the handle). An object is shown when a representation matches the current scale; the off-scale ones are hidden. When the current scale is unsupported by any representation, fall back to the base "1:1" copy instead of hiding everything (the object must not vanish) or showing everything (the copies must not stack). Model-space linetype scale. PSLTSCALE (a paper-space flag) was applied to model-space linetypes via the annotation scale, so a drawing saved at e.g. CANNOSCALE 10:1 drew its linetypes 10× off. Thread a `paper_space` flag through tessellate_entity and gate the PSLTSCALE factor on it, so it only scales linetypes for content shown inside a paper-space viewport; model space keeps LTSCALE × CELTSCALE. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
5e2b67c642
commit
d54fb9e2aa
5 files changed
+113
-2
No files matched your search
@@ -222,6 +222,59 @@ pub fn create_annotation_context(
|
||||
true
|
||||
}
|
||||
|
||||
/// True when `common` belongs to an annotative object whose per-object scale
|
||||
/// contexts are *all* bound to scales other than the current one — an
|
||||
/// off-scale representation that must stay hidden. A drawing may materialise
|
||||
/// each annotation scale as its own object (e.g. a block insert per scale on a
|
||||
/// "0 @ <scale>" layer); only the current scale's representation should draw.
|
||||
///
|
||||
/// False for non-annotative objects (no per-object context — the vast
|
||||
/// majority) and for objects whose contexts include the current scale. Gated
|
||||
/// on an extension dictionary so non-annotative entities skip the lookup.
|
||||
pub fn annotative_offscale(doc: &CadDocument, common: &EntityCommon) -> bool {
|
||||
if !common
|
||||
.xdictionary_handle
|
||||
.map(|h| !h.is_null())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let scales = object_scale_memberships(doc, common.handle);
|
||||
if scales.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let cur = &doc.header.current_annotation_scale;
|
||||
if scales.iter().any(|(name, _)| name.eq_ignore_ascii_case(cur)) {
|
||||
return false;
|
||||
}
|
||||
// Off-scale (no context for the current scale). If some representation in
|
||||
// the drawing DOES provide the current scale, hide this one — the matching
|
||||
// representation is the one to show.
|
||||
if current_scale_provided(doc) {
|
||||
return true;
|
||||
}
|
||||
// The current scale is unsupported by any representation. Fall back to the
|
||||
// base "1:1" representation: keep it, hide the enlarged copies — otherwise
|
||||
// every scale representation stacks (or, if all were hidden, the object
|
||||
// vanishes). Without this, opening at e.g. CANNOSCALE 10:1 shows both a 1×
|
||||
// and a 10× copy of the same block.
|
||||
!scales.iter().any(|(name, _)| name.eq_ignore_ascii_case("1:1"))
|
||||
}
|
||||
|
||||
/// Whether any annotative representation in the drawing targets the current
|
||||
/// annotation scale.
|
||||
fn current_scale_provided(doc: &CadDocument) -> bool {
|
||||
let cur = &doc.header.current_annotation_scale;
|
||||
doc.objects.values().any(|o| {
|
||||
if let ObjectType::ObjectContextData(cd) = o {
|
||||
if let Some(ObjectType::Scale(s)) = doc.objects.get(&cd.scale) {
|
||||
return s.name.eq_ignore_ascii_case(cur);
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
/// The annotation scales an object currently carries a per-object context for,
|
||||
/// as `(scale name, scale handle)` pairs (one per representation). Empty when
|
||||
/// the object has no per-object context chain.
|
||||
|
||||
Reference in new issue
Block a user