Merge pull request #1356 from ramox81/codex/fixed-constraint-parity

Match Fix geometric constraint behavior

# Conflicts:
#	src/scene/parametric_constraints.rs
#	src/scene/parametric_solve.rs
This commit is contained in:
Hakan Seven committed 2026-09-18 18:53:18 +03:00
commit 7ef4e9f336
9 files changed
+572 -203

No files matched your search

+48 -1
View File
@@ -593,7 +593,29 @@ impl ParametricConstraintSet {
///
/// Solver-side registration reads raw entity fields directly. This helper is
/// for UI-side consumers that need the current world-space position.
/// The single addressable point (marker `0`) of a point-like entity: the
/// node, insertion, or table origin the solver registers as its
/// `EntityGeom::Point` / text baseline start. `None` for curve entities,
/// whose marker `0` is a `source_points()` endpoint.
pub(crate) fn insertion_point(entity: &acadrust::EntityType) -> Option<Vector3> {
match entity {
acadrust::EntityType::Point(point) => Some(point.location),
acadrust::EntityType::Insert(insert) => Some(insert.insert_point),
acadrust::EntityType::Text(text) => Some(text.insertion_point),
acadrust::EntityType::MText(text) => Some(text.insertion_point),
acadrust::EntityType::AttributeDefinition(attribute) => Some(attribute.insertion_point),
acadrust::EntityType::AttributeEntity(attribute) => Some(attribute.insertion_point),
acadrust::EntityType::Table(table) => Some(table.insertion_point),
_ => None,
}
}
pub(crate) fn resolve_point(entity: &acadrust::EntityType, marker: i32) -> Option<Vector3> {
if marker == 0 {
if let Some(point) = insertion_point(entity) {
return Some(point);
}
}
if marker == -3 {
return match entity {
acadrust::EntityType::Circle(circle) => Some(circle.center_wcs()),
@@ -651,6 +673,12 @@ pub(crate) fn parametric_point_candidates(
.enumerate()
.map(|(marker, point)| (marker as i32, point))
.collect();
// A node / insertion point is a constraint point too (the reference
// fixes a POINT via NODe and TEXT via INSert), and these entities have
// no `source_points()` to collide with marker `0`.
if let Some(point) = insertion_point(entity) {
points.push((0, point));
}
match entity {
acadrust::EntityType::Circle(circle) => points.push((-3, circle.center_wcs())),
acadrust::EntityType::Arc(arc) => points.push((-3, arc.center_wcs())),
@@ -869,6 +897,23 @@ impl ConstraintKind {
}
}
/// Fixed draws a padlock (`src/ui/overlay.rs`), the way the reference bar
/// does: the plain symbol for a held curve or segment, this variant when one
/// addressable point is held (white lock with the point marker).
pub(crate) const FIXED_POINT_GLYPH: &str = "F·";
pub(crate) fn fixed_glyph_label(constraint: &ParametricConstraint) -> &'static str {
let point = constraint
.refs
.first()
.is_some_and(|reference| reference.marker.is_some() && reference.segment_index().is_none());
if point {
FIXED_POINT_GLYPH
} else {
ConstraintKind::Fixed.glyph_symbol()
}
}
/// The full glyph text for one constraint: its symbol, plus the driving
/// value for a dimensional kind (Distance/Angle/Radius).
pub(crate) fn glyph_label(constraint: &ParametricConstraint) -> String {
@@ -1672,7 +1717,9 @@ impl super::Scene {
})
.flat_map(|c| {
let is_conflicting = set.conflicts.iter().any(|(id, _)| *id == c.id);
let base_label = if show_values {
let base_label = if c.kind == ConstraintKind::Fixed {
fixed_glyph_label(c).to_string()
} else if show_values {
glyph_label(c)
} else {
c.kind.glyph_symbol().to_string()