Dimension text: DIMPOST's suffix also goes on tolerances (fixes #390) (#394)

With DIMTOL on, the DIMPOST suffix was added to the measurement only.
As in AutoCAD, the suffix (what follows `<>`, or the whole value when
there is no `<>`) now also follows each tolerance value: symmetric
(10.0mm±0.1mm) and stacked deviations alike. The prefix stays on the
measurement; limits are unchanged.

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Valentin KleinandClaude Opus 5.5 authored and GitHub committed 2026-10-10 18:43:20 -04:00
1 parent 9e19a10b29
commit 156bd0304e
2 files changed
+49 -3

No files matched your search

+5 -3
View File
@@ -290,11 +290,13 @@ fn linear_text(meas: f64, d: &Dimension, st: &DimStyle, prefix: &str) -> String
let mut s = post(&st.post, &main);
if st.tolerance && !st.limits {
let tf = NumFormat { decimals: st.tol_decimals, zin: st.tol_zero_suppression, round: 0.0, ..nf.clone() };
// DIMPOST's suffix (what follows `<>`, or all of it) also goes on the tolerance values.
let suffix = st.post.split_once("<>").map_or(st.post.as_str(), |(_, after)| after);
if (st.tol_plus - st.tol_minus).abs() < 1e-12 {
s += &format!("%%p{}", format_linear(st.tol_plus, &tf).1);
s += &format!("%%p{}{suffix}", format_linear(st.tol_plus, &tf).1);
} else {
let plus = format_linear(st.tol_plus, &tf).1;
let minus = format_linear(st.tol_minus, &tf).1;
let plus = format_linear(st.tol_plus, &tf).1 + suffix;
let minus = format_linear(st.tol_minus, &tf).1 + suffix;
let sign = |x: &str, pos: char| if x.trim_start_matches(['0', '.', ',']).is_empty() { x.to_string() } else { format!("{pos}{x}") };
let (plus, minus) =
(sign(&plus, '+'), if st.tol_minus < 0.0 { format!("+{}", minus.trim_start_matches('-')) } else { sign(&minus, '-') });
+44
View File
@@ -0,0 +1,44 @@
//! DIMPOST's suffix goes on the tolerance values as well as on the measurement (issue #390).
use cadcraft_doc::{DimKind, DimStyle, Dimension};
use cadcraft_geom::Vec3;
use cadcraft_render::dimension_geometry;
fn text(vars: serde_json::Value) -> (String, String) {
let d = Dimension {
kind: DimKind::Linear { rotation: 0.0 },
defpt: Vec3::new(0.0, 5.0, 0.0),
text_mid: Vec3::ZERO,
p13: Vec3::ZERO,
p14: Vec3::new(10.0, 0.0, 0.0),
p15: Vec3::ZERO,
p16: Vec3::ZERO,
text: String::new(),
style: "Standard".into(),
measurement: 0.0,
text_rotation: 0.0,
user_text_pos: false,
block: None,
overrides: Default::default(),
assoc: Vec::new(),
};
let mut st = DimStyle::default();
let rejected = st.apply_fields(vars.as_object().unwrap());
assert!(rejected.is_empty(), "unknown variables {rejected:?}");
let g = dimension_geometry(&d, &st, 1.0);
(g.value, g.mtext)
}
#[test]
fn dimpost_suffix_applies_to_tolerances() {
let sym = serde_json::json!({"DIMPOST": "mm", "DIMDEC": 1, "DIMTOL": 1, "DIMTP": 0.1, "DIMTM": 0.1, "DIMTDEC": 1});
assert_eq!(text(sym).0, "10.0mm±0.1mm");
// With `<>` only the part after it is the suffix; the prefix stays on the measurement.
let dev = serde_json::json!({"DIMPOST": "L=<> mm", "DIMDEC": 1, "DIMTOL": 1, "DIMTP": 0.1, "DIMTM": 0.2, "DIMTDEC": 1});
let (_, mtext) = text(dev);
assert!(mtext.starts_with("L=10.0 mm{"), "{mtext}");
assert!(mtext.contains("\\S+0.1 mm^-0.2 mm;"), "{mtext}");
// No DIMPOST: unchanged.
let plain = serde_json::json!({"DIMDEC": 1, "DIMTOL": 1, "DIMTP": 0.1, "DIMTM": 0.1, "DIMTDEC": 1});
assert_eq!(text(plain).0, "10.0±0.1");
}