forked from 1b-agent/opencadstudio-upstream
Fix perpendicular constraint behavior
This commit is contained in:
1 parent
a27545c379
commit
cbf1e76c69
8 files changed
+216
-16
No files matched your search
@@ -3245,6 +3245,23 @@ impl Scene {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn bump_entities_with_parametric_transform_policy(
|
||||
&mut self,
|
||||
changes: &[(Handle, ChangeKind)],
|
||||
driven_refs: &[parametric_constraints::ParametricRef],
|
||||
transformed_refs: &[parametric_constraints::ParametricRef],
|
||||
retained_originals: &[(Handle, EntityType)],
|
||||
) {
|
||||
self.bump_entities_with_solve_policy(
|
||||
changes,
|
||||
driven_refs,
|
||||
true,
|
||||
retained_originals,
|
||||
transformed_refs,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
fn bump_entities_with_solve_policy(
|
||||
&mut self,
|
||||
changes: &[(Handle, ChangeKind)],
|
||||
|
||||
+80
-1
@@ -161,6 +161,80 @@ impl Scene {
|
||||
.filter(|&h| !self.is_layer_locked(h))
|
||||
.collect();
|
||||
let handles = &handles[..];
|
||||
let retained_originals: Vec<(Handle, EntityType)> = handles
|
||||
.iter()
|
||||
.filter_map(|handle| {
|
||||
self.document
|
||||
.get_entity(*handle)
|
||||
.cloned()
|
||||
.map(|entity| (*handle, entity))
|
||||
})
|
||||
.collect();
|
||||
let transformed_refs: Vec<_> = handles
|
||||
.iter()
|
||||
.copied()
|
||||
.map(parametric_constraints::ParametricRef::whole)
|
||||
.collect();
|
||||
let mut driven_refs = Vec::new();
|
||||
if !matches!(t, EntityTransform::Translate(_)) {
|
||||
for set in &self.parametric_constraints {
|
||||
for constraint in &set.constraints {
|
||||
if !constraint.enabled
|
||||
|| !matches!(
|
||||
constraint.kind,
|
||||
parametric_constraints::ConstraintKind::Parallel
|
||||
| parametric_constraints::ConstraintKind::Perpendicular
|
||||
| parametric_constraints::ConstraintKind::Colinear
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let selected_refs = constraint
|
||||
.refs
|
||||
.iter()
|
||||
.filter(|reference| handles.contains(&reference.entity))
|
||||
.count();
|
||||
if selected_refs == 0 || selected_refs == constraint.refs.len() {
|
||||
continue;
|
||||
}
|
||||
for reference in constraint
|
||||
.refs
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|reference| !handles.contains(&reference.entity))
|
||||
{
|
||||
let anchor = if let Some(index) = reference.segment_index() {
|
||||
parametric_constraints::ParametricRef::point(
|
||||
reference.entity,
|
||||
index as i32,
|
||||
)
|
||||
} else if reference.directional_axis().is_some()
|
||||
&& matches!(
|
||||
self.document.get_entity(reference.entity),
|
||||
Some(EntityType::Ellipse(_))
|
||||
)
|
||||
{
|
||||
parametric_constraints::ParametricRef::center(reference.entity)
|
||||
} else {
|
||||
parametric_constraints::ParametricRef::point(reference.entity, 0)
|
||||
};
|
||||
let follows_selected_point = set.constraints.iter().any(|link| {
|
||||
link.enabled
|
||||
&& link.kind
|
||||
== parametric_constraints::ConstraintKind::Coincident
|
||||
&& link.refs.contains(&anchor)
|
||||
&& link
|
||||
.refs
|
||||
.iter()
|
||||
.any(|item| handles.contains(&item.entity))
|
||||
});
|
||||
if !follows_selected_point && !driven_refs.contains(&anchor) {
|
||||
driven_refs.push(anchor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Preserve readable text orientation when MIRRTEXT is disabled.
|
||||
let preserve_text_orientation =
|
||||
matches!(t, EntityTransform::Mirror { .. }) && !self.document.header.mirror_text;
|
||||
@@ -290,7 +364,12 @@ impl Scene {
|
||||
// per-handle, keeping the block cache + all other memoized wires.
|
||||
let changes: Vec<(Handle, ChangeKind)> =
|
||||
handles.iter().map(|&h| (h, ChangeKind::Modified)).collect();
|
||||
self.bump_entities(&changes);
|
||||
self.bump_entities_with_parametric_transform_policy(
|
||||
&changes,
|
||||
&driven_refs,
|
||||
&transformed_refs,
|
||||
&retained_originals,
|
||||
);
|
||||
self.refresh_meshes_for_handles(&refresh_solid_handles);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,6 +186,33 @@ pub(crate) fn directional_axis_endpoints(
|
||||
}
|
||||
}
|
||||
|
||||
/// Finite endpoints used to orient a line-like constraint reference.
|
||||
pub(crate) fn directional_reference_endpoints(
|
||||
entity: &acadrust::EntityType,
|
||||
reference: ParametricRef,
|
||||
) -> Option<[Vector3; 2]> {
|
||||
if reference.directional_axis().is_some() {
|
||||
return directional_axis_endpoints(entity, reference);
|
||||
}
|
||||
match entity {
|
||||
acadrust::EntityType::Line(line) if reference.marker.is_none() => {
|
||||
Some([line.start, line.end])
|
||||
}
|
||||
acadrust::EntityType::LwPolyline(_) | acadrust::EntityType::Polyline2D(_) => {
|
||||
let index = reference.segment_index()?;
|
||||
let points = super::dimension_assoc::source_points(entity);
|
||||
let start = *points.get(index)?;
|
||||
let end = if let Some(end) = points.get(index + 1) {
|
||||
*end
|
||||
} else {
|
||||
*points.first()?
|
||||
};
|
||||
Some([start, end])
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Grabbed points are exact kernel inputs; the solver anchors the remaining
|
||||
/// endpoint coordinates according to the line's directional constraints.
|
||||
pub(crate) fn grip_solve_anchor_refs(
|
||||
|
||||
@@ -2123,7 +2123,7 @@ fn solve_scope(
|
||||
for (handle, geom) in &cache {
|
||||
if initial_fixed_refs
|
||||
.iter()
|
||||
.any(|reference| reference.entity == *handle)
|
||||
.any(|reference| reference.entity == *handle && reference.marker.is_none())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user