From 7086a79c79ffc7697b267d1aa67a416ac9d348f1 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Thu, 25 Jun 2026 18:22:35 +0300 Subject: [PATCH] fix(dimension): render diameter text and shrink point markers (#139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues in a file whose dimensions carry baked *D### blocks. Missing diameter text: the baked MText values are "\U+220520" / "\U+220510" — the \U+2205 (⌀) escape immediately followed by the literal digits "20"/"10". The MText parser read up to six hex digits for a \U+ escape, so it greedily consumed "220520" = 0x220520, which is past the maximum code point, char::from_u32 returned None, and the whole text dropped. A \U+ escape is exactly four hex digits; read four so the symbol decodes and the trailing digits stay literal. (Angular "90\U+00B0" only worked because its escape sits at the end of the string.) Node artifacts: PDMODE=0 points were drawn as a fixed 0.1-world-unit "+", which in a small drawing turned the 31 dimension def-points on the Defpoints layer into visible crosses. Size the dot from world-per-pixel (~1 px, zoom-adaptive via the tessellation cache key) to match the near- invisible dot other CAD apps draw. Co-Authored-By: Claude Opus 4.8 --- src/entities/text_support.rs | 10 ++++++++-- src/scene/convert/tessellate.rs | 11 ++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/entities/text_support.rs b/src/entities/text_support.rs index 3820d3a03..842ec3a33 100644 --- a/src/entities/text_support.rs +++ b/src/entities/text_support.rs @@ -515,8 +515,14 @@ pub fn parse_mtext_paragraphs_ex( chars.next(); if chars.peek() == Some(&'+') { chars.next(); - let mut hex = String::with_capacity(6); - for _ in 0..6 { + // A `\U+XXXX` escape is exactly four hex digits (a BMP + // code point). Reading more greedily swallows the + // following literal characters — e.g. the diameter + // value `\U+220520` ("⌀20") was parsed as code point + // 0x220520, which is out of range, so the whole text + // vanished. (#139) + let mut hex = String::with_capacity(4); + for _ in 0..4 { match chars.peek() { Some(&c) if c.is_ascii_hexdigit() => { hex.push(chars.next().unwrap()); diff --git a/src/scene/convert/tessellate.rs b/src/scene/convert/tessellate.rs index feba76ea2..528b78e2e 100644 --- a/src/scene/convert/tessellate.rs +++ b/src/scene/convert/tessellate.rs @@ -286,7 +286,16 @@ pub fn tessellate( let result = tessellate_vertex(&v); match result { TruckTessResult::Point([x, y, z], [xl, yl, zl]) => { - let s = 0.1_f32; + // A PDMODE=0 point is a single dot. Size its marker to + // ~1 px so it reads as a dot rather than a large + // world-space "+" in small drawings — otherwise the + // dimension def-points on the Defpoints layer litter + // the view with crosses. The tessellation cache keys on + // world-per-pixel, so this re-sizes on zoom and stays a + // constant on-screen size. (#139) + let s = world_per_pixel + .map(|w| (w * 0.75).max(1e-6)) + .unwrap_or(0.1); let snap_pts = te.snap_pts; let key_vertices: Vec<[f64; 3]> = te .key_vertices