forked from 1b-agent/opencadstudio-upstream
Merge pull request #1334 from ramox81/codex/horizontal-constraint-parity
This commit is contained in:
commit
f9c59503f0
10 files changed
+710
-88
No files matched your search
+102
-59
@@ -1076,6 +1076,37 @@ fn build_constraint(
|
||||
let point_ref = |sys: &mut System, cache: &mut HashMap<_, _>, r: ParametricRef| {
|
||||
resolve_constraint_point(document, sys, cache, r)
|
||||
};
|
||||
let directional_line =
|
||||
|sys: &mut System, cache: &mut HashMap<_, _>, r: ParametricRef| {
|
||||
let geometry = resolve_ref(document, sys, cache, r)?;
|
||||
let minor_axis = matches!(
|
||||
r.directional_axis(),
|
||||
Some(super::parametric_constraints::DirectionalAxis::EllipseMinor)
|
||||
);
|
||||
let line = match geometry {
|
||||
EntityGeom::TextLine(line)
|
||||
if matches!(
|
||||
r.directional_axis(),
|
||||
Some(super::parametric_constraints::DirectionalAxis::TextBaseline)
|
||||
) => line,
|
||||
EntityGeom::Line(line) | EntityGeom::Ray(line) | EntityGeom::XLine(line)
|
||||
if r.marker.is_none() => line,
|
||||
EntityGeom::Polyline { .. } => geometry.line_segment(r.segment_index()?)?,
|
||||
EntityGeom::Ellipse(ellipse)
|
||||
if matches!(
|
||||
r.directional_axis(),
|
||||
Some(
|
||||
super::parametric_constraints::DirectionalAxis::EllipseMajor
|
||||
| super::parametric_constraints::DirectionalAxis::EllipseMinor
|
||||
)
|
||||
) => GLine {
|
||||
p1: ellipse.center,
|
||||
p2: ellipse.focus1,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
Some((line, minor_axis))
|
||||
};
|
||||
|
||||
let point_on_bounded_arc = |sys: &mut System, point: GPoint, arc: GArc| {
|
||||
let initial = BoundedArcValue::initial_parameter(sys.store(), point, arc);
|
||||
@@ -1108,30 +1139,49 @@ fn build_constraint(
|
||||
ConstraintKind::Coincident | ConstraintKind::Concentric | ConstraintKind::CenterPoint => {
|
||||
point_pair_equal(sys, cache, &c.refs)
|
||||
}
|
||||
ConstraintKind::Horizontal => match c.refs.as_slice() {
|
||||
[r] => whole_line(sys, cache, *r)
|
||||
.map(|line| {
|
||||
vec![Rc::new(Equal::new(line.p1.y, line.p2.y, 1.0)) as Rc<dyn Constraint>]
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
[a, b] => match (point_ref(sys, cache, *a), point_ref(sys, cache, *b)) {
|
||||
(Some(a), Some(b)) => vec![Rc::new(Equal::new(a.y, b.y, 1.0))],
|
||||
ConstraintKind::Horizontal | ConstraintKind::Vertical => {
|
||||
let fallback = if c.kind == ConstraintKind::Vertical {
|
||||
Vector3::UNIT_Y
|
||||
} else {
|
||||
Vector3::UNIT_X
|
||||
};
|
||||
let direction = c.axis_direction.unwrap_or(fallback);
|
||||
let length = direction.x.hypot(direction.y);
|
||||
let (dx, dy) = if length > 1.0e-12 {
|
||||
(direction.x / length, direction.y / length)
|
||||
} else {
|
||||
(fallback.x, fallback.y)
|
||||
};
|
||||
let datum = GLine {
|
||||
p1: GPoint::new(sys.add_param(0.0, true), sys.add_param(0.0, true)),
|
||||
p2: GPoint::new(sys.add_param(dx, true), sys.add_param(dy, true)),
|
||||
};
|
||||
match c.refs.as_slice() {
|
||||
[reference] => directional_line(sys, cache, *reference)
|
||||
.map(|(line, minor_axis)| {
|
||||
if minor_axis {
|
||||
vec![Rc::new(PerpendicularConstraint::new(
|
||||
sys.store(),
|
||||
line,
|
||||
datum,
|
||||
)) as Rc<dyn Constraint>]
|
||||
} else {
|
||||
vec![Rc::new(ParallelConstraint::new(sys.store(), line, datum))
|
||||
as Rc<dyn Constraint>]
|
||||
}
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
[a, b] => match (point_ref(sys, cache, *a), point_ref(sys, cache, *b)) {
|
||||
(Some(a), Some(b)) => vec![Rc::new(ParallelConstraint::new(
|
||||
sys.store(),
|
||||
GLine { p1: a, p2: b },
|
||||
datum,
|
||||
))],
|
||||
_ => Vec::new(),
|
||||
},
|
||||
_ => Vec::new(),
|
||||
},
|
||||
_ => Vec::new(),
|
||||
},
|
||||
ConstraintKind::Vertical => match c.refs.as_slice() {
|
||||
[r] => whole_line(sys, cache, *r)
|
||||
.map(|line| {
|
||||
vec![Rc::new(Equal::new(line.p1.x, line.p2.x, 1.0)) as Rc<dyn Constraint>]
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
[a, b] => match (point_ref(sys, cache, *a), point_ref(sys, cache, *b)) {
|
||||
(Some(a), Some(b)) => vec![Rc::new(Equal::new(a.x, b.x, 1.0))],
|
||||
_ => Vec::new(),
|
||||
},
|
||||
_ => Vec::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ConstraintKind::Parallel => {
|
||||
let [a, b] = c.refs.as_slice() else {
|
||||
return Vec::new();
|
||||
@@ -1147,39 +1197,6 @@ fn build_constraint(
|
||||
let [a, b] = c.refs.as_slice() else {
|
||||
return Vec::new();
|
||||
};
|
||||
let directional_line =
|
||||
|sys: &mut System, cache: &mut HashMap<_, _>, r: ParametricRef| {
|
||||
let geometry = resolve_ref(document, sys, cache, r)?;
|
||||
let minor_axis = matches!(
|
||||
r.directional_axis(),
|
||||
Some(super::parametric_constraints::DirectionalAxis::EllipseMinor)
|
||||
);
|
||||
let line = match geometry {
|
||||
EntityGeom::TextLine(line)
|
||||
if matches!(
|
||||
r.directional_axis(),
|
||||
Some(super::parametric_constraints::DirectionalAxis::TextBaseline)
|
||||
) => line,
|
||||
EntityGeom::Line(line) | EntityGeom::Ray(line) | EntityGeom::XLine(line)
|
||||
if r.marker.is_none() => line,
|
||||
EntityGeom::Polyline { .. } => {
|
||||
geometry.line_segment(r.segment_index()?)?
|
||||
}
|
||||
EntityGeom::Ellipse(ellipse)
|
||||
if matches!(
|
||||
r.directional_axis(),
|
||||
Some(
|
||||
super::parametric_constraints::DirectionalAxis::EllipseMajor
|
||||
| super::parametric_constraints::DirectionalAxis::EllipseMinor
|
||||
)
|
||||
) => GLine {
|
||||
p1: ellipse.center,
|
||||
p2: ellipse.focus1,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
Some((line, minor_axis))
|
||||
};
|
||||
let (Some((fixed, fixed_minor)), Some((moving, moving_minor))) =
|
||||
(directional_line(sys, cache, *a), directional_line(sys, cache, *b))
|
||||
else {
|
||||
@@ -2184,7 +2201,21 @@ fn constrained_line_axes(constraints: &[&ParametricConstraint]) -> HashMap<Param
|
||||
for c in constraints.iter().filter(|c| c.enabled) {
|
||||
if let [reference] = c.refs.as_slice() {
|
||||
if matches!(c.kind, ConstraintKind::Horizontal | ConstraintKind::Vertical) {
|
||||
axes.insert(*reference, c.kind == ConstraintKind::Vertical);
|
||||
let fallback = if c.kind == ConstraintKind::Vertical {
|
||||
Vector3::UNIT_Y
|
||||
} else {
|
||||
Vector3::UNIT_X
|
||||
};
|
||||
let direction = c.axis_direction.unwrap_or(fallback);
|
||||
let length = direction.x.hypot(direction.y);
|
||||
if length > 1.0e-12 {
|
||||
let (x, y) = (direction.x.abs() / length, direction.y.abs() / length);
|
||||
if x >= 1.0 - 1.0e-10 {
|
||||
axes.insert(*reference, false);
|
||||
} else if y >= 1.0 - 1.0e-10 {
|
||||
axes.insert(*reference, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2292,6 +2323,7 @@ fn solve_scope(
|
||||
rigid_points: Vec::new(),
|
||||
distance_direction_type: distance_direction_type::UNDIRECTED,
|
||||
distance_direction: None,
|
||||
axis_direction: None,
|
||||
angle_sector: angle_sector::PARALLEL_COUNTERCLOCKWISE,
|
||||
};
|
||||
for constraint in build_constraint(
|
||||
@@ -2617,7 +2649,12 @@ fn solve_scope(
|
||||
};
|
||||
let directional = set.constraints.iter().any(|constraint| {
|
||||
constraint.enabled
|
||||
&& constraint.kind == ConstraintKind::Perpendicular
|
||||
&& matches!(
|
||||
constraint.kind,
|
||||
ConstraintKind::Horizontal
|
||||
| ConstraintKind::Vertical
|
||||
| ConstraintKind::Perpendicular
|
||||
)
|
||||
&& constraint.refs.iter().any(|reference| {
|
||||
reference.entity == *handle && reference.directional_axis().is_some()
|
||||
})
|
||||
@@ -2658,7 +2695,12 @@ fn solve_scope(
|
||||
};
|
||||
let directional = set.constraints.iter().any(|constraint| {
|
||||
constraint.enabled
|
||||
&& constraint.kind == ConstraintKind::Perpendicular
|
||||
&& matches!(
|
||||
constraint.kind,
|
||||
ConstraintKind::Horizontal
|
||||
| ConstraintKind::Vertical
|
||||
| ConstraintKind::Perpendicular
|
||||
)
|
||||
&& constraint.refs.iter().any(|reference| {
|
||||
reference.entity == *handle
|
||||
&& matches!(
|
||||
@@ -3291,6 +3333,7 @@ impl Scene {
|
||||
rigid_points: Vec::new(),
|
||||
distance_direction_type: 0,
|
||||
distance_direction: None,
|
||||
axis_direction: None,
|
||||
angle_sector: angle_sector::PARALLEL_COUNTERCLOCKWISE,
|
||||
};
|
||||
let mut system = System::new();
|
||||
|
||||
Reference in new issue
Block a user