fix(dim): restore DIMTAD=Outside placement, route all DIMTAD values
The previous DIMTAD fix made every non-below value use the text-up side, which broke DIMTAD=2 (Outside) — that should sit on the side farthest from the measured points. Pass the DIMTAD value through instead of a below flag: above (1) / JIS (3) / centred (0) use the text-up side, below (4) the opposite, and outside (2) the away-from-object side. Tests cover above-up and outside-away. (#144) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ac5d92c0b4
commit
2a260be31d
1 changed files with 44 additions and 14 deletions
|
|
@ -2597,13 +2597,11 @@ fn text_on_dim_line(
|
||||||
text_w: f64,
|
text_w: f64,
|
||||||
arrow: f64,
|
arrow: f64,
|
||||||
dimtix: bool,
|
dimtix: bool,
|
||||||
below: bool,
|
tad: i16,
|
||||||
) -> Vector3 {
|
) -> Vector3 {
|
||||||
// "Above" (DIMTAD 1) places the text on the side its top points to — the
|
// The perpendicular "up" side: the perpendicular of the dimension line
|
||||||
// perpendicular of the dimension line normalised so the text reads
|
// normalised so the text reads left-to-right (or bottom-to-top when
|
||||||
// left-to-right (or bottom-to-top when vertical), NOT the side away from
|
// vertical). DIMTAD "above" (1) and JIS (3) sit on this side.
|
||||||
// the measured object. Keying the side off the object flipped "above" into
|
|
||||||
// "below" whenever the dimension ran the opposite way. (#144)
|
|
||||||
let (mut nx, mut ny) = (ax, ay);
|
let (mut nx, mut ny) = (ax, ay);
|
||||||
if nx < 0.0 || (nx == 0.0 && ny < 0.0) {
|
if nx < 0.0 || (nx == 0.0 && ny < 0.0) {
|
||||||
nx = -nx;
|
nx = -nx;
|
||||||
|
|
@ -2611,8 +2609,24 @@ fn text_on_dim_line(
|
||||||
}
|
}
|
||||||
let px = -ny;
|
let px = -ny;
|
||||||
let py = nx;
|
let py = nx;
|
||||||
// +perp is "above"; DIMTAD=4 (below) flips to the other side.
|
// DIMTAD side:
|
||||||
let perp_sign = if below { -1.0 } else { 1.0 };
|
// 1 (above) / 3 (JIS) / 0 (centred) → the text-up side, independent of the
|
||||||
|
// object — keying it off the object flipped "above" to "below" whenever
|
||||||
|
// the dimension ran the opposite way (#144);
|
||||||
|
// 4 (below) → the opposite side;
|
||||||
|
// 2 (outside) → the side farthest from the defining points (the object).
|
||||||
|
let perp_sign = match tad {
|
||||||
|
4 => -1.0,
|
||||||
|
2 => {
|
||||||
|
let off = (defpt.x - first.x) * px + (defpt.y - first.y) * py;
|
||||||
|
if off >= 0.0 {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
-1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => 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;
|
||||||
|
|
@ -2667,7 +2681,6 @@ fn dimension_text_pos_f64(
|
||||||
} else {
|
} else {
|
||||||
text_height * 0.5 + dimgap
|
text_height * 0.5 + dimgap
|
||||||
};
|
};
|
||||||
let tad_below = dimtad == 4;
|
|
||||||
// Rough text width + arrow allowance, used to decide text-outside fit.
|
// Rough text width + arrow allowance, used to decide text-outside fit.
|
||||||
let text_w = dimension_text_value(dim, style)
|
let text_w = dimension_text_value(dim, style)
|
||||||
.map(|t| t.chars().count() as f64 * text_height * 0.6 + 2.0 * dimgap)
|
.map(|t| t.chars().count() as f64 * text_height * 0.6 + 2.0 * dimgap)
|
||||||
|
|
@ -2699,7 +2712,7 @@ fn dimension_text_pos_f64(
|
||||||
text_w,
|
text_w,
|
||||||
arrow,
|
arrow,
|
||||||
dimtix,
|
dimtix,
|
||||||
tad_below,
|
dimtad,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Dimension::Aligned(d) => {
|
Dimension::Aligned(d) => {
|
||||||
|
|
@ -2717,7 +2730,7 @@ fn dimension_text_pos_f64(
|
||||||
text_w,
|
text_w,
|
||||||
arrow,
|
arrow,
|
||||||
dimtix,
|
dimtix,
|
||||||
tad_below,
|
dimtad,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -2769,13 +2782,30 @@ mod dimtad_tests {
|
||||||
let (first, second, defpt) = (v(0.0, 10.0), v(20.0, 10.0), v(0.0, 0.0));
|
let (first, second, defpt) = (v(0.0, 10.0), v(20.0, 10.0), v(0.0, 0.0));
|
||||||
let perp = 5.0;
|
let perp = 5.0;
|
||||||
let fwd =
|
let fwd =
|
||||||
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, false);
|
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||||
let rev =
|
let rev =
|
||||||
text_on_dim_line(first, second, defpt, -1.0, 0.0, 0, perp, 0.0, 1.0, false, false);
|
text_on_dim_line(first, second, defpt, -1.0, 0.0, 0, perp, 0.0, 1.0, false, 1);
|
||||||
assert!(fwd.y > 0.0, "above must be +Y, got {}", fwd.y);
|
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);
|
assert!(rev.y > 0.0, "above must be +Y even reversed, got {}", rev.y);
|
||||||
let below =
|
let below =
|
||||||
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, true);
|
text_on_dim_line(first, second, defpt, 1.0, 0.0, 0, perp, 0.0, 1.0, false, 4);
|
||||||
assert!(below.y < 0.0, "below must be -Y, got {}", below.y);
|
assert!(below.y < 0.0, "below must be -Y, got {}", below.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DIMTAD=Outside (2) stays on the side farthest from the measured points,
|
||||||
|
// whichever side of the geometry the dimension line is on.
|
||||||
|
#[test]
|
||||||
|
fn outside_is_away_from_object() {
|
||||||
|
let perp = 5.0;
|
||||||
|
// Object at y=0, dim line above it (y=10): away → further above.
|
||||||
|
let above = text_on_dim_line(
|
||||||
|
v(0.0, 0.0), v(20.0, 0.0), v(0.0, 10.0), 1.0, 0.0, 0, perp, 0.0, 1.0, false, 2,
|
||||||
|
);
|
||||||
|
assert!(above.y > 10.0, "outside must clear the object side, got {}", above.y);
|
||||||
|
// Object at y=0, dim line below it (y=-10): away → further below.
|
||||||
|
let below = text_on_dim_line(
|
||||||
|
v(0.0, 0.0), v(20.0, 0.0), v(0.0, -10.0), 1.0, 0.0, 0, perp, 0.0, 1.0, false, 2,
|
||||||
|
);
|
||||||
|
assert!(below.y < -10.0, "outside must clear the object side, got {}", below.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue