forked from 1b-agent/opencadstudio-upstream
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:
1 parent
fd2062bdec
commit
72fd3fd35b
9 files changed
+898
-36
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user