forked from 1b-agent/opencadstudio-upstream
fix(dimension): radius text stands above its line, which runs under it
A radius placed its text where it was clicked, on the line through the centre and the arc point, whatever DIMTAD said; outside the circle the line stopped at the text's near edge, so the text sat on the end of the line. DIMTAD now lifts aligned radius text off that line as it already does on a diameter, and an outside line runs on under the text to its far end. A text point already off the line (a file saved elsewhere) is kept as the text's middle. (#1675) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
12587339d8
commit
03cf0f75eb
1 file changed
+59
-21
+59
-21
@@ -3924,6 +3924,7 @@ fn tessellate_dimension_inner(
|
||||
dimtofl: style.map(|s| s.dimtofl).unwrap_or(false),
|
||||
text_position: text_layout.position,
|
||||
horizontal_text: text_layout.horizontal,
|
||||
text_lifted: style.map(|s| s.dimtad).unwrap_or(1) != 0,
|
||||
text_movement: style.map(|s| s.dimtmove).unwrap_or(0),
|
||||
text_break: text_layout.break_box,
|
||||
leader_anchor: style
|
||||
@@ -4847,6 +4848,8 @@ struct DimLineParams {
|
||||
dimtofl: bool,
|
||||
text_position: Vec3,
|
||||
horizontal_text: bool,
|
||||
/// DIMTAD lifts aligned text off its dimension line.
|
||||
text_lifted: bool,
|
||||
text_movement: i16,
|
||||
text_break: Option<TextBreak>,
|
||||
/// DIMTMOVE 1: the point the file stores is where the leader's hook starts,
|
||||
@@ -5531,6 +5534,14 @@ fn append_radial_leader(
|
||||
} else {
|
||||
add_segment(&mut g.dim_lines, tip, text_edge);
|
||||
}
|
||||
} else if params.text_lifted {
|
||||
// Text above or below the line: the line carries on out from the
|
||||
// rim, under the whole text to its far end.
|
||||
let along = normalized_or(direction, Vec3::X);
|
||||
let reach = (text - tip).dot(along) + params.text_width * 0.5;
|
||||
if reach > 0.0 {
|
||||
add_segment(&mut g.dim_lines, tip, tip + along * reach);
|
||||
}
|
||||
} else {
|
||||
let toward = normalized_or(text - tip, Vec3::X);
|
||||
let reach = ((text - tip).length() - params.text_width * 0.5).max(0.0);
|
||||
@@ -7893,18 +7904,47 @@ fn diameter_point_on_leader(
|
||||
point: Vector3,
|
||||
offset: f64,
|
||||
) -> bool {
|
||||
let (dx, dy) = (
|
||||
d.definition_point.x - d.angle_vertex.x,
|
||||
d.definition_point.y - d.angle_vertex.y,
|
||||
);
|
||||
point_on_line(d.angle_vertex, d.definition_point, point, offset)
|
||||
}
|
||||
|
||||
/// Whether `point` lies on the line through `a` and `b` rather than an
|
||||
/// `offset` (a DIMTAD lift) away from it.
|
||||
fn point_on_line(a: Vector3, b: Vector3, point: Vector3, offset: f64) -> bool {
|
||||
let (dx, dy) = (b.x - a.x, b.y - a.y);
|
||||
let length = dx.hypot(dy);
|
||||
if length < 1e-12 {
|
||||
return true;
|
||||
}
|
||||
let across = ((point.x - d.angle_vertex.x) * dy - (point.y - d.angle_vertex.y) * dx) / length;
|
||||
let across = ((point.x - a.x) * dy - (point.y - a.y) * dx) / length;
|
||||
across.abs() < offset.abs() * 0.5
|
||||
}
|
||||
|
||||
/// `point` on the line through `a` and `b`, lifted `offset` to the side the
|
||||
/// line's readable text stands on (below for DIMTAD 4).
|
||||
fn lift_off_line(a: Vector3, b: Vector3, point: Vector3, offset: f64, dimtad: i16) -> Vector3 {
|
||||
let (dx, dy) = (b.x - a.x, b.y - a.y);
|
||||
let len = (dx * dx + dy * dy).sqrt().max(1e-12);
|
||||
// Match the readable orientation used by text_on_dim_line().
|
||||
let (mut nx, mut ny) = (dx / len, dy / len);
|
||||
if nx < 0.0 || (nx == 0.0 && ny < 0.0) {
|
||||
nx = -nx;
|
||||
ny = -ny;
|
||||
}
|
||||
let (px, py) = (-ny, nx);
|
||||
let sign = if dimtad == 4 { -1.0 } else { 1.0 };
|
||||
Vector3::new(
|
||||
point.x + px * offset * sign,
|
||||
point.y + py * offset * sign,
|
||||
point.z,
|
||||
)
|
||||
}
|
||||
|
||||
/// DIMTOH / DIMTIH turn this dimension's text horizontal where it sits.
|
||||
fn dimension_text_reads_horizontal(dim: &Dimension, style: Option<&DimStyle>) -> bool {
|
||||
let outside = dimension_text_is_outside(dim, style);
|
||||
style.is_some_and(|style| (outside && style.dimtoh) || (!outside && style.dimtih))
|
||||
}
|
||||
|
||||
fn dimension_text_pos_f64(
|
||||
dim: &Dimension,
|
||||
style: Option<&DimStyle>,
|
||||
@@ -7956,6 +7996,18 @@ fn dimension_text_pos_f64(
|
||||
let side = if point.x >= tip.x { 1.0 } else { -1.0 };
|
||||
Vector3::new(point.x + side * (arrow + text_w * 0.5), point.y, point.z)
|
||||
}
|
||||
// A radius places its text where it was clicked, on the line
|
||||
// through the centre and the arc point; DIMTAD lifts aligned text
|
||||
// off that line as it does on a diameter, and the line runs on
|
||||
// under it. A point already off the line is the text's own
|
||||
// middle, as a file saved elsewhere writes it. (#1675)
|
||||
Dimension::Radius(d)
|
||||
if dimtad != 0
|
||||
&& !dimension_text_reads_horizontal(dim, style)
|
||||
&& point_on_line(d.angle_vertex, d.definition_point, point, perp_off) =>
|
||||
{
|
||||
lift_off_line(d.angle_vertex, d.definition_point, point, perp_off, dimtad)
|
||||
}
|
||||
// A diameter whose text the user dragged keeps the grip point on
|
||||
// the leader and lifts the text by the DIMTAD offset (#1323).
|
||||
// A stored point already standing off the leader is the text's
|
||||
@@ -7966,22 +8018,7 @@ fn dimension_text_pos_f64(
|
||||
&& dimtad != 0
|
||||
&& diameter_point_on_leader(d, point, perp_off) =>
|
||||
{
|
||||
let dx = d.definition_point.x - d.angle_vertex.x;
|
||||
let dy = d.definition_point.y - d.angle_vertex.y;
|
||||
let len = (dx * dx + dy * dy).sqrt().max(1e-12);
|
||||
// Match the readable orientation used by text_on_dim_line().
|
||||
let (mut nx, mut ny) = (dx / len, dy / len);
|
||||
if nx < 0.0 || (nx == 0.0 && ny < 0.0) {
|
||||
nx = -nx;
|
||||
ny = -ny;
|
||||
}
|
||||
let (px, py) = (-ny, nx);
|
||||
let perp_sign = if dimtad == 4 { -1.0 } else { 1.0 };
|
||||
Vector3::new(
|
||||
point.x + px * perp_off * perp_sign,
|
||||
point.y + py * perp_off * perp_sign,
|
||||
point.z,
|
||||
)
|
||||
lift_off_line(d.angle_vertex, d.definition_point, point, perp_off, dimtad)
|
||||
}
|
||||
_ => point,
|
||||
};
|
||||
@@ -8248,6 +8285,7 @@ pub(crate) fn baked_large_radial_geometry(
|
||||
dimtofl: style.is_some_and(|style| style.dimtofl),
|
||||
text_position: text.position,
|
||||
horizontal_text: text.horizontal,
|
||||
text_lifted: style.map(|style| style.dimtad).unwrap_or(1) != 0,
|
||||
text_movement: style.map(|style| style.dimtmove).unwrap_or(0),
|
||||
text_break: text.break_box,
|
||||
leader_anchor: None,
|
||||
|
||||
Reference in new issue
Block a user