fix(dimension): plain value for DIMLIM without offsets, stored angle for degenerate angular text

A limits style whose upper and lower offsets are both zero prints the plain
value in AutoCAD, not a stack of two equal numbers. A three-point angular
dimension whose extension point sits on its vertex has no measurable angle;
AutoCAD keeps showing the angle it stored, and the text now does too instead
of reading 0 degrees. Both cases came out of comparing saved picture blocks
with regenerated text across a set of production drawings.
This commit is contained in:
Christopher Overbeck committed 2026-09-16 18:28:58 -05:00
1 parent 1474376924
commit a30db2d4f3
1 file changed
+61 -11
+61 -11
View File
@@ -6179,8 +6179,8 @@ fn dimension_text_parts(
// lower one and no nominal, so the tolerance slot stays empty.
let value = match limits_text(dim, style, is_angular) {
Some(limits) => limits,
None if is_angular => format_angular_value(dim.measurement(), style),
None => format_linear_value(dim.measurement(), style),
None if is_angular => format_angular_value(display_measurement(dim), style),
None => format_linear_value(display_measurement(dim), style),
};
let primary_raw = match dim {
Dimension::Radius(_) | Dimension::LargeRadial(_) => format!("R{}", value),
@@ -6217,11 +6217,29 @@ fn dimension_text_parts(
Some((primary, tolerance_suffix))
}
/// The value the text reports. An angular dimension whose extension point
/// sits on its vertex has no measurable angle; AutoCAD then keeps showing the
/// angle it stored (group 42, radians) rather than 0°, and so do we.
fn display_measurement(dim: &Dimension) -> f64 {
let measured = dim.measurement();
let stored = dim.base().actual_measurement;
match dim {
Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)
if measured.abs() < 1e-9 && stored.abs() > 1e-9 =>
{
stored.to_degrees()
}
_ => measured,
}
}
/// DIMLIM: the upper limit stacked over the lower one, replacing the nominal.
/// The offsets apply to the displayed number, so DIMLFAC and DIMRND come first.
fn limits_text(dim: &Dimension, style: Option<&DimStyle>, is_angular: bool) -> Option<String> {
let s = style.filter(|s| s.dimlim)?;
let measurement = dim.measurement();
// With both offsets zero AutoCAD prints the plain value, not a stack of
// two equal numbers.
let s = style.filter(|s| s.dimlim && (s.dimtp.abs() > 1e-12 || s.dimtm.abs() > 1e-12))?;
let measurement = display_measurement(dim);
if is_angular {
return Some(format!(
"\\S{}^{};",
@@ -8058,12 +8076,6 @@ mod limits_format_tests {
dimension_text_parts(&horizontal(), Some(&s)),
Some((r"\S10.02^9.92;".to_string(), None))
);
s.dimtp = 0.0;
s.dimtm = 0.0;
assert_eq!(
dimension_text_parts(&horizontal(), Some(&s)),
Some((r"\S10^10;".to_string(), None))
);
}
// The offsets apply to the number the reader sees, which for a paper
@@ -8078,11 +8090,24 @@ mod limits_format_tests {
Some((r"\S75.020^74.950;".to_string(), None))
);
s.dimrnd = 0.5;
s.dimtm = 0.0;
assert_eq!(
dimension_text_parts(&horizontal(), Some(&s)),
Some((r"\S75.020^75.000;".to_string(), None))
);
}
// DIMLIM with both offsets at zero is a plain value in AutoCAD, not a
// stack of two equal numbers.
#[test]
fn limits_without_offsets_show_the_plain_value() {
let mut s = style();
s.dimlim = true;
s.dimtp = 0.0;
s.dimtm = 0.0;
assert_eq!(
dimension_text_parts(&horizontal(), Some(&s)),
Some((r"\S75.000^75.000;".to_string(), None))
Some(("10.000".to_string(), None))
);
}
@@ -8135,6 +8160,31 @@ mod limits_format_tests {
assert_eq!(text_cells(r"\S10.020^9.950; REF", 1.0), 6.0 + 4.0);
}
// A three-point angular dimension whose first extension point coincides
// with the vertex measures nothing; the stored angle keeps the text.
#[test]
fn degenerate_angular_dimension_reports_its_stored_angle() {
use acadrust::entities::DimensionAngular3Pt;
let mut d = DimensionAngular3Pt::default();
d.angle_vertex = Vector3::new(6.0, 4.85, 0.0);
d.first_point = d.angle_vertex;
d.second_point = Vector3::new(7.0, 4.85, 0.0);
d.definition_point = Vector3::new(8.0, 5.4, 0.0);
d.base.actual_measurement = std::f64::consts::FRAC_PI_4;
let dim = Dimension::Angular3Pt(d);
let mut s = style();
s.dimadec = 0;
assert_eq!(
dimension_text_parts(&dim, Some(&s)),
Some(("45°".to_string(), None))
);
s.dimlim = true;
s.dimtp = 0.1;
s.dimtm = 0.1;
let (value, _) = dimension_text_parts(&dim, Some(&s)).unwrap();
assert!(value.starts_with(r"\S45"), "{value}");
}
#[test]
fn a_limits_stack_is_two_halves_tall() {
let mut s = style();