From f6f4317b7fca03c6dabcbdbc1b8fc32a5622a786 Mon Sep 17 00:00:00 2001 From: NgoQuocViet2001 Date: Wed, 19 Aug 2026 21:19:34 +0700 Subject: [PATCH] fix(point): keep DDPTYPE off dimension definition points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dimension definition points come out of a DWG as ordinary POINT entities on the Defpoints layer, so the header's PDMODE applied to them like any other point. Opening a drawing authored elsewhere with a point style set stamped that glyph on every dimension end, burying the drawing under crosses and circles. They are a dimension's bookkeeping, not draughting the user placed, so resolve PDMODE to 0 for them and leave the single pixel-sized dot. Both render paths — the header one and the viewport-aware relative-PDSIZE one — go through the same resolution, so a relative PDSIZE cannot bring the glyph back. Fixes #790 --- src/entities/point.rs | 79 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/src/entities/point.rs b/src/entities/point.rs index e6fdd65a3..dd1182099 100644 --- a/src/entities/point.rs +++ b/src/entities/point.rs @@ -82,7 +82,7 @@ pub fn relative_render( return None; }; let pdsize = document.header.point_display_size; - let pdmode = document.header.point_display_mode; + let pdmode = effective_pdmode(pt, document.header.point_display_mode); if pdsize > 0.0 || pdmode == 0 { return None; } @@ -173,8 +173,26 @@ fn point_glyph(cx: f64, cy: f64, z: f64, pdmode: i16, s_half: f64) -> Vec<[f64; pts } +/// Layer AutoCAD writes dimension definition points to. +const DEFPOINTS_LAYER: &str = "DEFPOINTS"; + +/// PDMODE as it applies to `pt`. +/// +/// Definition points are ordinary POINT entities on the Defpoints layer, but +/// they are a dimension's bookkeeping rather than draughting the user placed. +/// Letting DDPTYPE stamp its glyph on them buries a drawing imported from other +/// software under crosses and circles at every dimension end, so they stay the +/// pixel-sized dot whatever the header says. (#378, #790) +fn effective_pdmode(pt: &Point, pdmode: i16) -> i16 { + if pt.common.layer.eq_ignore_ascii_case(DEFPOINTS_LAYER) { + 0 + } else { + pdmode + } +} + fn to_render(pt: &Point, document: &acadrust::CadDocument) -> RenderEntity { - let pdmode = document.header.point_display_mode; + let pdmode = effective_pdmode(pt, document.header.point_display_mode); let s = pdsize_world(document.header.point_display_size) * 0.5; point_render(pt, pdmode, s) } @@ -240,3 +258,60 @@ impl RenderConvertible for Point { } crate::impl_entity_basics!(Point); + +#[cfg(test)] +mod tests { + use super::*; + + fn point_on(layer: &str) -> Point { + let mut pt = Point::default(); + pt.common.layer = layer.to_string(); + pt.location = acadrust::types::Vector3::new(1.0, 2.0, 0.0); + pt + } + + /// #378 / #790: DDPTYPE must not reach a dimension's definition points. + #[test] + fn definition_points_ignore_the_point_style() { + let mut doc = acadrust::CadDocument::new(); + // Circle-enclosed cross: the style that made imported drawings unreadable. + doc.header.point_display_mode = 34; + doc.header.point_display_size = 2.0; + + let drawn = to_render(&point_on("0"), &doc); + assert!( + matches!(drawn.object, RenderObject::Lines(ref pts) if !pts.is_empty()), + "a point the user placed still follows PDMODE" + ); + + for layer in ["Defpoints", "DEFPOINTS", "defpoints"] { + let defpoint = to_render(&point_on(layer), &doc); + assert!( + matches!(defpoint.object, RenderObject::Dot(_)), + "a definition point on {layer} must stay a dot" + ); + } + } + + /// The relative-PDSIZE path hands the glyph a viewport size; it must make + /// the same call, or a definition point would come back as a sized cross. + #[test] + fn definition_points_ignore_the_point_style_at_relative_pdsize() { + let mut doc = acadrust::CadDocument::new(); + doc.header.point_display_mode = 34; + doc.header.point_display_size = -5.0; + + let drawn = relative_render(&EntityType::Point(point_on("0")), &doc, Some(0.01)); + assert!(drawn.is_some(), "a user point still takes the viewport-aware path"); + + let defpoint = relative_render( + &EntityType::Point(point_on("Defpoints")), + &doc, + Some(0.01), + ); + assert!( + defpoint.is_none(), + "a definition point falls through to the dot instead of a sized glyph" + ); + } +}