forked from 1b-agent/opencadstudio-upstream
Dynamic dimensions: reference text format, horizontal text, lock after the text
A plain number shows as typed (d1=100), an expression under the fx: prefix (fx: d2=d1*2); the text stays horizontal through DIMTIH/DIMTOH overrides and the lock mark follows the text. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
0b5c686371
commit
aa51765a62
3 files changed
+52
-25
No files matched your search
@@ -3611,6 +3611,7 @@ impl OpenCADStudio {
|
|||||||
};
|
};
|
||||||
let text = dynamic_dimension_text(
|
let text = dynamic_dimension_text(
|
||||||
&name,
|
&name,
|
||||||
|
&expression,
|
||||||
value,
|
value,
|
||||||
self.tabs[i].scene.constraint_name_format,
|
self.tabs[i].scene.constraint_name_format,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6295,8 +6295,8 @@ fn dimension_text_is_outside(dim: &Dimension, style: Option<&DimStyle>) -> bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where a dynamic dimension's lock mark sits: just before the text on its
|
/// Where a dynamic dimension's lock mark sits: just after the (horizontal)
|
||||||
/// baseline, with the direction that points away from the text.
|
/// text, with the direction that points away from the text.
|
||||||
pub(crate) fn dynamic_dimension_lock_anchor(
|
pub(crate) fn dynamic_dimension_lock_anchor(
|
||||||
document: &CadDocument,
|
document: &CadDocument,
|
||||||
dim: &Dimension,
|
dim: &Dimension,
|
||||||
@@ -6317,13 +6317,7 @@ pub(crate) fn dynamic_dimension_lock_anchor(
|
|||||||
let stack_scale = style.map(dimtfac_or_one).unwrap_or(1.0);
|
let stack_scale = style.map(dimtfac_or_one).unwrap_or(1.0);
|
||||||
let half_width = text_cells(&value, stack_scale) * text_height * CELL_WIDTH * 0.5;
|
let half_width = text_cells(&value, stack_scale) * text_height * CELL_WIDTH * 0.5;
|
||||||
let pos = dimension_text_pos_f64(dim, style, text_height, dim_scale);
|
let pos = dimension_text_pos_f64(dim, style, text_height, dim_scale);
|
||||||
let rot = if dim.base().text_rotation.abs() > 1e-9 {
|
let outward = Vector3::new(1.0, 0.0, 0.0);
|
||||||
dim.base().text_rotation
|
|
||||||
} else {
|
|
||||||
dimension_text_natural_rotation(dim)
|
|
||||||
};
|
|
||||||
let (sr, cr) = rot.sin_cos();
|
|
||||||
let outward = Vector3::new(-cr, -sr, 0.0);
|
|
||||||
Some((
|
Some((
|
||||||
Vector3::new(
|
Vector3::new(
|
||||||
pos.x + outward.x * half_width,
|
pos.x + outward.x * half_width,
|
||||||
|
|||||||
@@ -368,12 +368,23 @@ pub const DYNAMIC_DIMENSION_GLYPH: &str = "\u{1F512}";
|
|||||||
pub const DYNAMIC_DIMENSION_TEXT_PX: f32 = 12.0;
|
pub const DYNAMIC_DIMENSION_TEXT_PX: f32 = 12.0;
|
||||||
|
|
||||||
/// The text a dynamic dimension shows: CONSTRAINTNAMEFORMAT 0 = name,
|
/// The text a dynamic dimension shows: CONSTRAINTNAMEFORMAT 0 = name,
|
||||||
/// 1 = value, 2 = name=value.
|
/// 1 = value, 2 = name=value. A plain number shows as typed (`d1=100`); an
|
||||||
pub(crate) fn dynamic_dimension_text(name: &str, value: f64, format: u8) -> String {
|
/// expression shows the expression under the reference's `fx:` prefix
|
||||||
|
/// (`fx: d2=d1*2`).
|
||||||
|
pub(crate) fn dynamic_dimension_text(name: &str, source: &str, value: f64, format: u8) -> String {
|
||||||
|
let source = source.trim();
|
||||||
|
let literal = source.parse::<f64>().is_ok();
|
||||||
|
let shown = if literal {
|
||||||
|
source.to_string()
|
||||||
|
} else {
|
||||||
|
measured_expression(value)
|
||||||
|
};
|
||||||
match format {
|
match format {
|
||||||
0 => name.to_string(),
|
0 => name.to_string(),
|
||||||
1 => format!("{value:.4}"),
|
1 if literal => shown,
|
||||||
_ => format!("{name}={value:.4}"),
|
1 => format!("fx: {shown}"),
|
||||||
|
_ if literal => format!("{name}={shown}"),
|
||||||
|
_ => format!("fx: {name}={source}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1477,14 +1488,24 @@ impl super::Scene {
|
|||||||
let Some(constraint) = set.get(*id) else {
|
let Some(constraint) = set.get(*id) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let (name, value) = match &constraint.driving_param {
|
let (name, source, value) = match &constraint.driving_param {
|
||||||
Some(DrivingValue::Named(name)) => {
|
Some(DrivingValue::Named(name)) => (
|
||||||
(name.clone(), table.resolve(name).unwrap_or(f64::NAN))
|
name.clone(),
|
||||||
|
table
|
||||||
|
.get(name)
|
||||||
|
.map(|parameter| parameter.source.clone())
|
||||||
|
.unwrap_or_default(),
|
||||||
|
table.resolve(name).unwrap_or(f64::NAN),
|
||||||
|
),
|
||||||
|
Some(DrivingValue::Literal(value)) => {
|
||||||
|
(String::new(), measured_expression(*value), *value)
|
||||||
}
|
}
|
||||||
Some(DrivingValue::Literal(value)) => (String::new(), *value),
|
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
updates.push((*dimension, dynamic_dimension_text(&name, value, format)));
|
updates.push((
|
||||||
|
*dimension,
|
||||||
|
dynamic_dimension_text(&name, &source, value, format),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (handle, text) in updates {
|
for (handle, text) in updates {
|
||||||
@@ -1615,19 +1636,30 @@ impl super::Scene {
|
|||||||
.filter(|height| *height > 1e-9)
|
.filter(|height| *height > 1e-9)
|
||||||
.unwrap_or(0.18);
|
.unwrap_or(0.18);
|
||||||
let scale = f64::from(band) * f64::from(DYNAMIC_DIMENSION_TEXT_PX) / text_height;
|
let scale = f64::from(band) * f64::from(DYNAMIC_DIMENSION_TEXT_PX) / text_height;
|
||||||
let current = crate::entities::dim_override::real(
|
use crate::entities::dim_override as ov;
|
||||||
&dimension.base().common.extended_data,
|
let xdata = &dimension.base().common.extended_data;
|
||||||
crate::entities::dim_override::DIMSCALE,
|
let current = ov::real(xdata, ov::DIMSCALE);
|
||||||
);
|
// The reference draws dynamic dimension text horizontally.
|
||||||
if current.is_some_and(|value| (value - scale).abs() < 1e-9) {
|
let horizontal = ov::int(xdata, ov::DIMTIH) == Some(1) && ov::int(xdata, ov::DIMTOH) == Some(1);
|
||||||
|
if current.is_some_and(|value| (value - scale).abs() < 1e-9) && horizontal {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
crate::entities::dim_override::set(
|
ov::set(
|
||||||
&mut self.document,
|
&mut self.document,
|
||||||
handle,
|
handle,
|
||||||
crate::entities::dim_override::DIMSCALE,
|
ov::DIMSCALE,
|
||||||
Some(acadrust::xdata::XDataValue::Real(scale)),
|
Some(acadrust::xdata::XDataValue::Real(scale)),
|
||||||
);
|
);
|
||||||
|
if !horizontal {
|
||||||
|
for code in [ov::DIMTIH, ov::DIMTOH] {
|
||||||
|
ov::set(
|
||||||
|
&mut self.document,
|
||||||
|
handle,
|
||||||
|
code,
|
||||||
|
Some(acadrust::xdata::XDataValue::Integer16(1)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
changes.push((handle, super::ChangeKind::Modified));
|
changes.push((handle, super::ChangeKind::Modified));
|
||||||
}
|
}
|
||||||
if !changes.is_empty() {
|
if !changes.is_empty() {
|
||||||
|
|||||||
Reference in new issue
Block a user