fix(dimension): lay automatic text out from the style again (#1412)

Since the stored text point became authoritative (85619f49), new linear
and aligned dimensions drew their text at the placeholder the commands
stored (the middle of the dimension line), so DIMTAD Above/Below and the
text offset had no effect; a style or override edit left the stale point
in place too.

reset_automatic_text_position clears the point of text the user did not
place, so it is laid out from the current settings. DIMLINEAR, DIMALIGNED,
DIMBASELINE, DIMCONTINUE and QDIM call it on creation; a DIMSTYLE edit, a
dimension override row and a style change call it for the dimensions they
touch. Loaded, untouched dimensions keep their pictured position.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-25 22:20:16 +03:00
1 parent eb84bae779
commit 83e1ebd44a
8 files changed
+44 -2

No files matched your search

+5
View File
@@ -479,6 +479,11 @@ impl OpenCADStudio {
})
.collect();
for handle in stale {
if let Some(codec::EntityType::Dimension(dimension)) =
self.tabs[tab].scene.document.get_entity_mut(handle)
{
crate::entities::dimension::reset_automatic_text_position(dimension.base_mut());
}
self.tabs[tab].scene.invalidate_dim_block_recorded(handle);
}
+17
View File
@@ -450,11 +450,28 @@ fn split_template(value: &str) -> (&str, &str) {
value.split_once("<>").unwrap_or(("", value))
}
/// Apply a dimension override row. A changed override lays automatic text
/// out afresh, so e.g. a new DIMTAD moves it off the stored position.
pub fn set_property(
doc: &mut CadDocument,
handle: Handle,
field: &str,
value: &str,
) -> bool {
let applied = apply_property(doc, handle, field, value);
if applied {
if let Some(EntityType::Dimension(dimension)) = doc.get_entity_mut(handle) {
crate::entities::dimension::reset_automatic_text_position(dimension.base_mut());
}
}
applied
}
fn apply_property(
doc: &mut CadDocument,
handle: Handle,
field: &str,
value: &str,
) -> bool {
let trimmed = value.trim();
if field == "dim_center_type" {
+11
View File
@@ -373,6 +373,7 @@ fn apply_base_prop(base: &mut DimensionBase, field: &str, value: &str) -> bool {
}
"style_name" => {
base.style_name = value.to_string();
reset_automatic_text_position(base);
true
}
// Editing the text position in the properties panel pins it to a
@@ -7620,6 +7621,16 @@ fn stored_text_point(dim: &Dimension) -> Option<Vector3> {
(p.x * p.x + p.y * p.y + p.z * p.z > 1e-16).then_some(p)
}
/// Clear an automatic text position so the dimension is laid out from its
/// current settings again. A loaded point is kept so a drawing looks as it
/// was drawn; a new dimension, or one whose style or overrides just changed,
/// has no valid one. Text the user placed keeps its point (#1412).
pub(crate) fn reset_automatic_text_position(base: &mut DimensionBase) {
if !base.text_user_positioned {
base.text_middle_point = Vector3::new(0.0, 0.0, 0.0);
}
}
/// The point on the circle a radial leader leaves from: the arc point of a
/// radius, or whichever end of a diameter's chord is nearer the text.
fn radial_leader_tip(dim: &Dimension, text: Vector3) -> Vector3 {
+1
View File
@@ -92,6 +92,7 @@ pub(crate) fn aligned_dimension_entity(
let (d1, d2) = dim_line_endpoints(first, second, point);
dim.base.text_middle_point = v3((d1 + d2) * 0.5);
dim.base.insertion_point = dim.base.text_middle_point;
crate::entities::dimension::reset_automatic_text_position(&mut dim.base);
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override);
EntityType::Dimension(Dimension::Aligned(dim))
+2
View File
@@ -546,6 +546,7 @@ fn build_linear(
result.base.definition_point = result.definition_point;
result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5));
result.base.insertion_point = result.base.text_middle_point;
crate::entities::dimension::reset_automatic_text_position(&mut result.base);
Some(Dimension::Aligned(result))
} else {
let mut result = DimensionLinear::new(world(plane, fixed), world(plane, point));
@@ -554,6 +555,7 @@ fn build_linear(
result.base.definition_point = result.definition_point;
result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5));
result.base.insertion_point = result.base.text_middle_point;
crate::entities::dimension::reset_automatic_text_position(&mut result.base);
Some(Dimension::Linear(result))
}
}
+6 -2
View File
@@ -453,6 +453,7 @@ fn build_linear(
result.base.definition_point = result.definition_point;
result.base.text_middle_point = world(plane, first_line.lerp(second_line, 0.5));
result.base.insertion_point = result.base.text_middle_point;
crate::entities::dimension::reset_automatic_text_position(&mut result.base);
Dimension::Linear(result)
}
@@ -565,7 +566,8 @@ fn preview_for_dimension(dimension: &Dimension) -> WireModel {
project(&plane, value.second_point),
value.rotation,
project(&plane, value.definition_point),
project(&plane, value.base.text_middle_point),
(value.base.text_middle_point != Vector3::ZERO)
.then(|| project(&plane, value.base.text_middle_point)),
value.base.actual_measurement,
);
}
@@ -634,7 +636,7 @@ fn linear_preview(
second: Vec2,
rotation: f64,
definition: Vec2,
text: Vec2,
text: Option<Vec2>,
measurement: f64,
) {
let axis = Vec2::new(rotation.cos(), rotation.sin());
@@ -642,6 +644,8 @@ fn linear_preview(
let coordinate = definition.dot(perpendicular);
let first_line = project_to_line(first, perpendicular, coordinate);
let second_line = project_to_line(second, perpendicular, coordinate);
// Automatic text stores no point; mark the middle of the dimension line.
let text = text.unwrap_or_else(|| first_line.lerp(second_line, 0.5));
segment(points, plane, first, first_line);
segment(points, plane, second, second_line);
segment(points, plane, first_line, second_line);
+1
View File
@@ -140,6 +140,7 @@ pub(crate) fn linear_dimension_entity(
dim.base.definition_point = dim.definition_point;
dim.base.text_middle_point = v3(linear_text_pos(first, second, point, axis));
dim.base.insertion_point = dim.base.text_middle_point;
crate::entities::dimension::reset_automatic_text_position(&mut dim.base);
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override);
EntityType::Dimension(Dimension::Linear(dim))
+1
View File
@@ -201,6 +201,7 @@ impl QdimCommand {
dimension.base.definition_point = v3(definition);
dimension.base.text_middle_point = v3(text);
dimension.base.insertion_point = v3(text);
crate::entities::dimension::reset_automatic_text_position(&mut dimension.base);
dimension.base.actual_measurement = dimension.measurement();
let association = DimensionAssociationInput::Explicit(vec![first.sources.first().copied(), second.sources.first().copied()]);
(self.plane.place_entity(EntityType::Dimension(Dimension::Linear(dimension))), association)