diff --git a/crates/render/src/dim.rs b/crates/render/src/dim.rs index 4d02c3b..c8bae88 100644 --- a/crates/render/src/dim.rs +++ b/crates/render/src/dim.rs @@ -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, '-') }); diff --git a/crates/render/tests/dim_post_tolerance.rs b/crates/render/tests/dim_post_tolerance.rs new file mode 100644 index 0000000..24ee288 --- /dev/null +++ b/crates/render/tests/dim_post_tolerance.rs @@ -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"); +}