Linear dimensional constraints: point flow, dynamic dimension, driving parameter

DCLINEAR, DCHORIZONTAL, DCVERTICAL and DCALIGNED follow the reference flow:
`Specify first constraint point or [Object] <Object>:`, `Specify second
constraint point:`, `Specify dimension line location:`, then `Dimension
text = …` and `Enter value or name and value <d1=100>:`. Linear reads
horizontal or vertical from the dimension line location the way a linear
dimension does; Object takes a line's, an arc's or a polyline segment's
ends. A miss reports `No valid constraint point found.` / `No object
found.` and asks again; another object type reports `Invalid selection for
Linear. Select a line, polyline segment or arc.`.

Each constraint creates a drawing parameter (`d1`, `d2`, …, or the typed
`name=expression`), drives the constraint through it, and draws a dynamic
dimension in constraint gray whose text follows CONSTRAINTNAMEFORMAT
(`d1=100.0000`); the dimension is associated with the constrained objects
and its text is refreshed after every solve. A typed value other than the
measured one moves the second point while the first stays, and so does a
later parameter edit. Deleting the constraint removes its dimension and,
when nothing else reads it, its parameter.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ramox81andClaude Fable 5.1 committed 2026-09-21 11:53:19 +03:00
1 parent fd2062bdec
commit 72fd3fd35b
9 files changed
+898 -36

No files matched your search

+25 -15
View File
@@ -67,26 +67,36 @@ impl AlignedDimensionCommand {
let first = self.plane.to_local(first);
let second = self.plane.to_local(second);
let point = self.plane.to_local(point);
let mut dim = DimensionAligned::new(v3(first), v3(second));
// The placement point is stored so commit matches the preview.
dim.definition_point = v3(point);
dim.base.definition_point = v3(point);
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;
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(
&mut dim.base,
self.text_override.clone(),
);
let mut entity = aligned_dimension_entity(first, second, point, self.text_override.clone());
// An explicit text angle overrides the default rotation.
if let Some(angle) = self.text_angle {
dim.base.text_rotation = angle;
if let (Some(angle), EntityType::Dimension(dimension)) = (self.text_angle, &mut entity) {
dimension.base_mut().text_rotation = angle;
}
self.plane.place_entity(EntityType::Dimension(Dimension::Aligned(dim)))
self.plane.place_entity(entity)
}
}
/// An aligned dimension between two points of the working plane, its
/// dimension line through `point` — what DIMALIGNED places and what an
/// aligned dimensional constraint draws.
pub(crate) fn aligned_dimension_entity(
first: DVec3,
second: DVec3,
point: DVec3,
text_override: Option<String>,
) -> EntityType {
let mut dim = DimensionAligned::new(v3(first), v3(second));
// The placement point is stored so commit matches the preview.
dim.definition_point = v3(point);
dim.base.definition_point = v3(point);
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;
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override);
EntityType::Dimension(Dimension::Aligned(dim))
}
impl CadCommand for AlignedDimensionCommand {
fn set_working_plane(&mut self, plane: WorkingPlane) {
self.plane = plane;
+27 -15
View File
@@ -15,7 +15,7 @@ use glam::DVec3;
use crate::t;
/// Select the measured axis from where the dimension line clears the points.
fn measure_axis(first: DVec3, second: DVec3, def: DVec3) -> DVec3 {
pub(crate) fn measure_axis(first: DVec3, second: DVec3, def: DVec3) -> DVec3 {
let outside = |value: f64, a: f64, b: f64| {
let (low, high) = if a <= b { (a, b) } else { (b, a) };
(low - value).max(value - high).max(0.0)
@@ -113,26 +113,38 @@ impl LinearDimensionCommand {
let first = self.plane.to_local(first);
let second = self.plane.to_local(second);
let point = self.plane.to_local(point);
let mut dim = DimensionLinear::new(v3(first), v3(second));
let axis = self.axis_mode.axis(first, second, point);
dim.rotation = axis.y.atan2(axis.x);
dim.set_offset(dimension_line_offset(second, point, axis));
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;
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(
&mut dim.base,
self.text_override.clone(),
);
let mut entity =
linear_dimension_entity(first, second, point, axis, self.text_override.clone());
// An explicit text angle overrides the UCS-derived rotation.
if let Some(angle) = self.text_angle {
dim.base.text_rotation = angle;
if let (Some(angle), EntityType::Dimension(dimension)) = (self.text_angle, &mut entity) {
dimension.base_mut().text_rotation = angle;
}
self.plane.place_entity(EntityType::Dimension(Dimension::Linear(dim)))
self.plane.place_entity(entity)
}
}
/// A linear dimension between two points of the working plane, its
/// dimension line through `point` along `axis` — what DIMLINEAR places and
/// what a dynamic dimensional constraint draws.
pub(crate) fn linear_dimension_entity(
first: DVec3,
second: DVec3,
point: DVec3,
axis: DVec3,
text_override: Option<String>,
) -> EntityType {
let mut dim = DimensionLinear::new(v3(first), v3(second));
dim.rotation = axis.y.atan2(axis.x);
dim.set_offset(dimension_line_offset(second, point, axis));
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;
dim.base.actual_measurement = dim.measurement();
crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override);
EntityType::Dimension(Dimension::Linear(dim))
}
impl CadCommand for LinearDimensionCommand {
fn name(&self) -> &'static str {
"DIMLINEAR"