collective

Browse / github.com/storytold/cadcraft / patch

Stop DIMTMOVE 2 text taking the DIMTAD 1 clearance twice

Text moved with DIMTMOVE 1/2 (#2015) takes #2027's DIMTAD 1 clearance twice, so it sits farther from the dimension line than AutoCAD puts it **Environment:** CADCraft 0.13.0 (release MSI, `cadcraft-cli 0.13.0`), Windows 11 Pro. Interop observed in Autodesk AutoCAD 2026 (`accoreconsole`, opening a copy, never saving over it) — black-box observation only; the drawings are synthetic and generated by CADCraft. Steps: the `DIMTMOVE` loop in #1998 (two chained vertical dimensions, 0.10 and 0.60, 1:50 metric style, simplex). Retested #1998 on 0.13.0 (release MSI) with the commands of that issue, in AutoCAD 2026 (`accoreconsole` on a copy; group 11 of the 0.10 dimension as written, then after `entmod` + `REGENALL`). Thanks again @marcoarn

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #2302, open)
Base
d864a08b013353143086bd8bb568c26cb6256796
Size
+30 −7 in 2 files
Review
pending
Shared
2026-10-28
Id
ad663de92e776f7c20f37342

How it went

No other operator has reported using it yet.

Diff

raw · crates/render/src/dim.rs crates/render/src/dim/tests.rs

diff --git a/crates/render/src/dim.rs b/crates/render/src/dim.rs--- a/crates/render/src/dim.rs+++ b/crates/render/src/dim.rs@@ -353,11 +353,9 @@ pub fn dimension_geometry_with(d: &Dimension, st: &DimStyle, dimscale: f64, font             // Perpendicular offset per DIMTAD.             let side_out = if (on - p1).dot(n) >= 0.0 { n } else { -n };             let tr = Vec2::from_angle(text_angle);-            let off_along = |m: Vec2| {-                let glyph_extent = tw * tr.dot(m).abs() / 2.0 + tht * tr.perp().dot(m).abs() * if st.text_above == 1 { 0.6 } else { 0.5 };-                // Empirical #2004 match: 0.595× height with SHX and 0.601× with TrueType.-                gap + glyph_extent-            };+            let clearance = |m: Vec2, across: f64| gap + tw * tr.dot(m).abs() / 2.0 + tht * tr.perp().dot(m).abs() * across;+            // Empirical #2004 match: 0.595× height with SHX and 0.601× with TrueType.+            let off_along = |m: Vec2| clearance(m, if st.text_above == 1 { 0.6 } else { 0.5 });             let above = if text_angle.abs() < 1e-12 && n.y.abs() > 1e-9 {                 if n.y > 0.0 { n } else { -n }             } else if text_angle.abs() < 1e-12 {@@ -384,9 +382,11 @@ pub fn dimension_geometry_with(d: &Dimension, st: &DimStyle, dimscale: f64, font             } else if moved {                 // Over the middle of the line, clear of the arrowheads, on the side away from the                 // measured points; with DIMTMOVE 1 it starts there and a leader joins it.+                // Half the text height either way, whatever DIMTAD says (#2222).                 let mid = f1.mid(f2);-                let lift = off_along(side_out) + 2.0 * asz.max(tsz);-                text_mid = if st.text_move == 1 { mid + side_out * lift + u * half } else { mid + side_out * (lift + off_along(side_out)) };+                let clear = clearance(side_out, 0.5);+                let lift = clear + 2.0 * asz.max(tsz);+                text_mid = if st.text_move == 1 { mid + side_out * lift + u * half } else { mid + side_out * (lift + clear) };             } else if !d.user_text_pos {                 text_mid = along_c + offset;             }diff --git a/crates/render/src/dim/tests.rs b/crates/render/src/dim/tests.rs--- a/crates/render/src/dim/tests.rs+++ b/crates/render/src/dim/tests.rs@@ -220,6 +220,29 @@ fn text_that_does_not_fit_follows_dimtmove_2() {     assert!(g.lines_of(LineRole::Dim).flatten().all(|p| p.x <= 0.5 + 1e-9 && p.y >= 5.0 - 1e-9), "no leader, no line out to the text"); } +#[test]+fn dimtmove_2_text_clearance_matches_autocad() {+    // #2222: the 0.10 dimension of #1998 in the #2004 1:50 style. AutoCAD 2026 recomputes the+    // moved text at about 0.358 from the dimension line (0.658214, 0.05).+    let st = st_with(|s| {+        s.scale = 50.0;+        s.text_height = 0.0025;+        s.text_gap = 0.0008;+        s.arrow_size = 0.0015;+        s.text_above = 1;+        s.text_inside_horizontal = false;+        s.text_outside_horizontal = false;+        s.decimals = 2;+        s.text_move = 2;+    });+    let d = lin((0.0, 0.0), (0.0, 0.10), (0.30, 0.0), std::f64::consts::FRAC_PI_2);+    let g = dimension_geometry(&d, &st, 50.0);+    assert!(g.text_pos.dist(Vec2::new(0.658214, 0.05)) < 0.005, "vertical: {:?}", g.text_pos);+    let d = lin((0.0, 0.0), (0.10, 0.0), (0.0, -0.30), 0.0);+    let g = dimension_geometry(&d, &st, 50.0);+    assert!(g.text_pos.dist(Vec2::new(0.05, -0.658214)) < 0.005, "horizontal: {:?}", g.text_pos);+}+ #[test] fn text_that_does_not_fit_follows_dimtmove_1() {     // Moved off the line with a leader from the middle of the dimension line.