fix(dim): place DIMTAD "above" text by text-up side, not object side

Dimension text vertical placement chose the perpendicular side away from the
measured points, so "Above" (DIMTAD 1) flipped to below whenever the
dimension line sat on the opposite side of the geometry. Place it on the side
the text top points to instead — the perpendicular of the dimension line
normalised to read left-to-right — independent of the object. (#144)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-20 17:32:56 +03:00
commit ac5d92c0b4

View file

@ -2599,15 +2599,20 @@ fn text_on_dim_line(
dimtix: bool, dimtix: bool,
below: bool, below: bool,
) -> Vector3 { ) -> Vector3 {
let px = -ay; // "Above" (DIMTAD 1) places the text on the side its top points to — the
let py = ax; // perpendicular of the dimension line normalised so the text reads
// Side of the measured points the dimension line sits on (the "above" // left-to-right (or bottom-to-top when vertical), NOT the side away from
// side). DIMTAD=4 (below) flips the text to the other side. // the measured object. Keying the side off the object flipped "above" into
let off = (defpt.x - first.x) * px + (defpt.y - first.y) * py; // "below" whenever the dimension ran the opposite way. (#144)
let mut perp_sign = if off >= 0.0 { 1.0 } else { -1.0 }; let (mut nx, mut ny) = (ax, ay);
if below { if nx < 0.0 || (nx == 0.0 && ny < 0.0) {
perp_sign = -perp_sign; nx = -nx;
ny = -ny;
} }
let px = -ny;
let py = nx;
// +perp is "above"; DIMTAD=4 (below) flips to the other side.
let perp_sign = if below { -1.0 } else { 1.0 };
// Along-axis positions of the extension points relative to the dim line. // Along-axis positions of the extension points relative to the dim line.
let t1 = (first.x - defpt.x) * ax + (first.y - defpt.y) * ay; let t1 = (first.x - defpt.x) * ax + (first.y - defpt.y) * ay;
let t2 = (second.x - defpt.x) * ax + (second.y - defpt.y) * ay; let t2 = (second.x - defpt.x) * ax + (second.y - defpt.y) * ay;
@ -2747,3 +2752,30 @@ fn dimension_text_pos_f64(
fn perp_sign_default() -> f64 { fn perp_sign_default() -> f64 {
1.0 1.0
} }
#[cfg(test)]
mod dimtad_tests {
use super::text_on_dim_line;
use acadrust::types::Vector3;
fn v(x: f64, y: f64) -> Vector3 {
Vector3::new(x, y, 0.0)
}
// DIMTAD=Above must place text on the geometric "up" side of a horizontal
// dimension whichever way the dimension runs; DIMTAD=Below flips it. (#144)
#[test]
fn above_is_up_regardless_of_direction() {
let (first, second, defpt) = (v(0.0, 10.0), v(20.0, 10.0), v(0.0, 0.0));
let perp = 5.0;
let fwd =
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, false);
let rev =
text_on_dim_line(first, second, defpt, -1.0, 0.0, 0, perp, 0.0, 1.0, false, false);
assert!(fwd.y > 0.0, "above must be +Y, got {}", fwd.y);
assert!(rev.y > 0.0, "above must be +Y even reversed, got {}", rev.y);
let below =
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, true);
assert!(below.y < 0.0, "below must be -Y, got {}", below.y);
}
}