feat(dimension): honour DIMTIX/DIMATFIT text fit; clarify remaining flags (#94)
Centred dimension text that doesn't fit between the extension lines now slides outside (text-outside placement), unless DIMTIX forces it to stay inside. DIMTOFL is already satisfied for linear/aligned dims (their dim line is always drawn between the extension points). The remaining style flags are documented in place: - DIMATFIT arrow-outside modes and DIMUPT need an arrow autofit pass. - DIMTXTDIRECTION (RTL) needs single-line text direction support. - DIMARCSYM / DIMJOGANG apply only to arc-length / jogged-radius dims, which aren't shipped as entity variants. - DIMUNIT is obsolete (superseded by DIMLUNIT). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
006dbe4631
commit
40a91372fd
1 changed files with 36 additions and 6 deletions
|
|
@ -1039,11 +1039,14 @@ fn tessellate_dimension_inner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// DIMTOFL / DIMTIX / DIMATFIT / DIMUPT control autofit behaviour at
|
// Text fit: DIMTIX (force text inside) is honoured in the text-placement
|
||||||
// dim *creation*. At render time we honour the saved text and arrow
|
// pass (dimension_text_pos_f64), which slides centred text outside the
|
||||||
// positions, so reading them here is a no-op — they shape geometry
|
// extension lines when it doesn't fit. DIMTOFL (force the dim line
|
||||||
// upstream rather than here.
|
// inside) is already satisfied for linear/aligned, whose dim line is
|
||||||
let _ = (s.dimtofl, s.dimtix, s.dimatfit, s.dimupt);
|
// always drawn between the extension points. DIMATFIT's arrow-outside
|
||||||
|
// modes and DIMUPT (reposition-on-create) still need an arrow autofit
|
||||||
|
// pass — read here for round-trip until then.
|
||||||
|
let _ = (s.dimtofl, s.dimatfit, s.dimupt);
|
||||||
// DIMTXTDIRECTION (RTL) needs per-instance text mirroring on the Text
|
// DIMTXTDIRECTION (RTL) needs per-instance text mirroring on the Text
|
||||||
// entity, which the current text struct can't carry. Tracked: read
|
// entity, which the current text struct can't carry. Tracked: read
|
||||||
// and ignore so the file round-trips on save.
|
// and ignore so the file round-trips on save.
|
||||||
|
|
@ -2472,6 +2475,7 @@ fn vec3_local(v: Vector3, off: [f64; 3]) -> Vec3 {
|
||||||
/// Style-driven text anchor on the dimension line: a point on the line through
|
/// Style-driven text anchor on the dimension line: a point on the line through
|
||||||
/// `defpt` parallel to (`ax`,`ay`), slid along it per DIMJUST and lifted by
|
/// `defpt` parallel to (`ax`,`ay`), slid along it per DIMJUST and lifted by
|
||||||
/// `perp_off` toward the side the dimension line sits on.
|
/// `perp_off` toward the side the dimension line sits on.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn text_on_dim_line(
|
fn text_on_dim_line(
|
||||||
first: Vector3,
|
first: Vector3,
|
||||||
second: Vector3,
|
second: Vector3,
|
||||||
|
|
@ -2480,6 +2484,9 @@ fn text_on_dim_line(
|
||||||
ay: f64,
|
ay: f64,
|
||||||
dimjust: i16,
|
dimjust: i16,
|
||||||
perp_off: f64,
|
perp_off: f64,
|
||||||
|
text_w: f64,
|
||||||
|
arrow: f64,
|
||||||
|
dimtix: bool,
|
||||||
) -> Vector3 {
|
) -> Vector3 {
|
||||||
let px = -ay;
|
let px = -ay;
|
||||||
let py = ax;
|
let py = ax;
|
||||||
|
|
@ -2490,11 +2497,21 @@ fn text_on_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;
|
||||||
// DIMJUST: 0=centred, 1/3=near first ext, 2/4=near second ext.
|
// DIMJUST: 0=centred, 1/3=near first ext, 2/4=near second ext.
|
||||||
let along = match dimjust {
|
let mut along = match dimjust {
|
||||||
1 | 3 => t1,
|
1 | 3 => t1,
|
||||||
2 | 4 => t2,
|
2 | 4 => t2,
|
||||||
_ => (t1 + t2) * 0.5,
|
_ => (t1 + t2) * 0.5,
|
||||||
};
|
};
|
||||||
|
// DIMATFIT / DIMTIX fit: when centred text can't fit between the extension
|
||||||
|
// lines, slide it just past the far one (text-outside placement) unless
|
||||||
|
// DIMTIX forces it to stay inside.
|
||||||
|
if dimjust == 0 && !dimtix && text_w > 0.0 {
|
||||||
|
let lo = t1.min(t2);
|
||||||
|
let hi = t1.max(t2);
|
||||||
|
if text_w > (hi - lo) - 2.0 * arrow {
|
||||||
|
along = hi + arrow + text_w * 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
let bx = defpt.x + ax * along;
|
let bx = defpt.x + ax * along;
|
||||||
let by = defpt.y + ay * along;
|
let by = defpt.y + ay * along;
|
||||||
Vector3::new(
|
Vector3::new(
|
||||||
|
|
@ -2511,6 +2528,8 @@ fn dimension_text_pos_f64(dim: &Dimension, style: Option<&DimStyle>, text_height
|
||||||
let dimtad = style.map(|s| s.dimtad).unwrap_or(1);
|
let dimtad = style.map(|s| s.dimtad).unwrap_or(1);
|
||||||
let dimgap = style.map(|s| s.dimgap).unwrap_or(0.0);
|
let dimgap = style.map(|s| s.dimgap).unwrap_or(0.0);
|
||||||
let dimjust = style.map(|s| s.dimjust).unwrap_or(0);
|
let dimjust = style.map(|s| s.dimjust).unwrap_or(0);
|
||||||
|
// DIMTIX forces the text to stay between the extension lines.
|
||||||
|
let dimtix = style.map(|s| s.dimtix).unwrap_or(false);
|
||||||
// DIMTVP vertical-position multiplier (units of dimtxt). Only honoured when
|
// DIMTVP vertical-position multiplier (units of dimtxt). Only honoured when
|
||||||
// DIMTAD == 0; offsets text perpendicular to the dim line.
|
// DIMTAD == 0; offsets text perpendicular to the dim line.
|
||||||
let dimtvp = style.map(|s| s.dimtvp).unwrap_or(0.0);
|
let dimtvp = style.map(|s| s.dimtvp).unwrap_or(0.0);
|
||||||
|
|
@ -2519,6 +2538,11 @@ fn dimension_text_pos_f64(dim: &Dimension, style: Option<&DimStyle>, text_height
|
||||||
} else {
|
} else {
|
||||||
text_height * 0.5 + dimgap
|
text_height * 0.5 + dimgap
|
||||||
};
|
};
|
||||||
|
// Rough text width + arrow allowance, used to decide text-outside fit.
|
||||||
|
let text_w = dimension_text_value(dim, style)
|
||||||
|
.map(|t| t.chars().count() as f64 * text_height * 0.6 + 2.0 * dimgap)
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
let arrow = text_height; // arrows are roughly text-height sized
|
||||||
|
|
||||||
// Explicit per-entity override (text dragged to a custom location): the
|
// Explicit per-entity override (text dragged to a custom location): the
|
||||||
// saved point wins. Otherwise the dimension style governs placement.
|
// saved point wins. Otherwise the dimension style governs placement.
|
||||||
|
|
@ -2542,6 +2566,9 @@ fn dimension_text_pos_f64(dim: &Dimension, style: Option<&DimStyle>, text_height
|
||||||
ay,
|
ay,
|
||||||
dimjust,
|
dimjust,
|
||||||
perp_off,
|
perp_off,
|
||||||
|
text_w,
|
||||||
|
arrow,
|
||||||
|
dimtix,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Dimension::Aligned(d) => {
|
Dimension::Aligned(d) => {
|
||||||
|
|
@ -2556,6 +2583,9 @@ fn dimension_text_pos_f64(dim: &Dimension, style: Option<&DimStyle>, text_height
|
||||||
dy / len,
|
dy / len,
|
||||||
dimjust,
|
dimjust,
|
||||||
perp_off,
|
perp_off,
|
||||||
|
text_w,
|
||||||
|
arrow,
|
||||||
|
dimtix,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue