fix: preserve selected smooth curve geometry

This commit is contained in:
Hakan Seven committed 2026-09-17 17:19:09 +03:00
1 parent 76451f7298
commit e8125c8702
5 files changed
+157 -4

No files matched your search

+1 -1
View File
@@ -1206,7 +1206,7 @@ impl OpenCADStudio {
}
}
"GCSMOOTH" | "SMOOTHCONSTRAINT" => {
"GCSMOOTH" => {
use crate::modules::parametric::SmoothConstraintCommand;
let handles = self.tabs[i].scene.selected_handles_in_order();
if handles.is_empty() {
+26
View File
@@ -1390,4 +1390,30 @@ mod tests {
acadrust::types::Vector3::new(0.0, 2.5, 0.0)
);
}
#[test]
fn showing_derived_fit_points_does_not_change_the_curve() {
let mut spline = Spline::default();
spline.degree = 3;
spline.control_points = vec![
acadrust::types::Vector3::new(0.0, 0.0, 0.0),
acadrust::types::Vector3::new(1.0, 3.0, 0.0),
acadrust::types::Vector3::new(4.0, 3.0, 0.0),
acadrust::types::Vector3::new(5.0, 0.0, 0.0),
];
spline.knots = cadkernel::space::clamped_uniform_knots(3, 4);
let before = nurbs3(&spline).unwrap().point_at(0.37);
assert!(prepare_fit_point_view(&mut spline));
spline.cv_frame_visible = false;
assert!(shows_fit_points(&spline));
assert!(!uses_fit_method(&spline));
let after = nurbs3(&spline).unwrap().point_at(0.37);
assert!(
cadkernel::space::Vec3::from(before)
.distance(cadkernel::space::Vec3::from(after))
< 1.0e-12
);
}
}
+1 -1
View File
@@ -138,7 +138,7 @@ impl CadModule for ParametricModule {
inventory::submit!(crate::command::CommandRegistration {
names: &[
"AUTOCONSTRAIN", "CONSTRAINTSETTINGS", "GCSMOOTH", "SMOOTHCONSTRAINT", "GCSHOW", "GCHIDE", "GCRESET",
"AUTOCONSTRAIN", "CONSTRAINTSETTINGS", "GCSMOOTH", "GCSHOW", "GCHIDE", "GCRESET",
"GCSHOWALL", "GCHIDEALL", "DCSHOW", "DCHIDE", "DCSHOWALL", "DCHIDEALL",
"DCCONVERT", "DELCONSTRAINT",
]
+32 -2
View File
@@ -74,8 +74,10 @@ impl SmoothConstraintCommand {
})
}
EntityType::LwPolyline(_) | EntityType::Polyline2D(_) => {
let (source, _, _) = crate::scene::centerline::picked_source(entity, handle, point)?;
let segment = usize::try_from(source.segment_index).ok()?;
let planar = crate::entities::curve::entity_curve(entity)?;
let local = planar.plane.project(point.to_array())?;
let segments = planar.curve.segments();
let (segment, _) = cadkernel::geom2d::nearest_of(segments.iter(), local)?;
let points = crate::scene::dimension_assoc::source_points(entity);
let closed = match entity {
EntityType::LwPolyline(polyline) => polyline.is_closed,
@@ -229,3 +231,31 @@ impl CadCommand for SmoothConstraintCommand {
CmdResult::Cancel
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn polyline_target_keeps_the_picked_arc_segment_and_endpoint() {
let handle = Handle::new(7);
let mut polyline = acadrust::entities::LwPolyline::new();
polyline.vertices = vec![
acadrust::entities::LwVertex::from_coords(0.0, 0.0),
acadrust::entities::LwVertex::with_bulge(
acadrust::types::Vector2::new(5.0, 0.0),
1.0,
),
acadrust::entities::LwVertex::from_coords(10.0, 0.0),
];
let target = SmoothConstraintCommand::target_reference(
&EntityType::LwPolyline(polyline),
handle,
DVec3::new(10.0, 0.0, 0.0),
)
.expect("arc endpoint");
assert_eq!(target.curve, ParametricRef::segment(handle, 1));
assert_eq!(target.endpoint, ParametricRef::point(handle, 2));
}
}
+97
View File
@@ -3977,4 +3977,101 @@ mod tests {
assert!(jet.tangent[1].abs() < 1e-9, "jet={jet:?}");
assert!(cadkernel::space::Vec3::from(jet.curvature).length() < 5e-3);
}
#[test]
fn smooth_constraint_uses_the_selected_polyline_arc_curvature() {
let mut scene = Scene::new();
let mut target = acadrust::entities::LwPolyline::new();
target.vertices = vec![
acadrust::entities::LwVertex::with_bulge(
acadrust::types::Vector2::new(0.0, 0.0),
1.0,
),
acadrust::entities::LwVertex::from_coords(10.0, 0.0),
];
let target = scene.add_entity(EntityType::LwPolyline(target));
let mut spline = acadrust::entities::Spline::new();
spline.degree = 3;
spline.control_points = vec![
Vector3::new(2.0, 1.0, 0.0),
Vector3::new(3.0, 2.0, 0.0),
Vector3::new(4.0, 3.0, 0.0),
Vector3::new(5.0, 3.0, 0.0),
];
spline.knots = cadkernel::space::clamped_uniform_knots(3, 4);
let spline = scene.add_entity(EntityType::Spline(spline));
scene
.parametric_constraint_set_mut(ParametricScope::ModelSpace)
.add(
ConstraintKind::Smooth,
vec![
ParametricRef::point(spline, 0),
ParametricRef::point(target, 0),
ParametricRef::segment(target, 0),
],
None,
);
scene.bump_entities(&[(target, super::ChangeKind::Modified)]);
let EntityType::Spline(spline) = scene.document.get_entity(spline).unwrap() else {
panic!("expected spline");
};
let curve = crate::entities::spline::nurbs3(spline).unwrap();
let jet =
cadkernel::space::CurveJet::from_nurbs(&curve, cadkernel::space::SplineEnd::Start)
.unwrap();
assert!(cadkernel::space::Vec3::from(jet.point).length() < 1.0e-9);
assert!(jet.tangent[0].abs() < 1.0e-9, "jet={jet:?}");
assert!(
(cadkernel::space::Vec3::from(jet.curvature).length() - 0.2).abs() < 2.0e-4,
"jet={jet:?}"
);
}
#[test]
fn smooth_constraint_accepts_a_stale_normal_on_an_arbitrary_plane() {
let mut scene = Scene::new();
let target = scene.add_entity(EntityType::Line(
acadrust::entities::Line::from_points(
Vector3::new(0.0, 0.0, 1.0),
Vector3::new(5.0, 0.0, 1.0),
),
));
let mut source = acadrust::entities::Spline::new();
source.degree = 3;
source.normal = Vector3::UNIT_Z;
source.control_points = vec![
Vector3::new(1.0, 0.0, 0.0),
Vector3::new(2.0, 0.0, 2.0),
Vector3::new(4.0, 0.0, 2.0),
Vector3::new(5.0, 0.0, 3.0),
];
source.knots = cadkernel::space::clamped_uniform_knots(3, 4);
let source = scene.add_entity(EntityType::Spline(source));
let refs = vec![
ParametricRef::point(source, 0),
ParametricRef::point(target, 0),
];
assert!(scene
.validate_parametric_constraint(ConstraintKind::Smooth, &refs, None)
.is_ok());
scene
.parametric_constraint_set_mut(ParametricScope::ModelSpace)
.add(ConstraintKind::Smooth, refs, None);
scene.bump_entities(&[(target, super::ChangeKind::Modified)]);
let EntityType::Spline(source) = scene.document.get_entity(source).unwrap() else {
panic!("expected spline");
};
let curve = crate::entities::spline::nurbs3(source).unwrap();
let jet =
cadkernel::space::CurveJet::from_nurbs(&curve, cadkernel::space::SplineEnd::Start)
.unwrap();
assert!(cadkernel::space::Vec3::from(jet.point)
.distance(cadkernel::space::Vec3::new(0.0, 0.0, 1.0))
< 1.0e-9);
assert!(jet.tangent[1].abs() < 1.0e-9 && jet.tangent[2].abs() < 1.0e-9);
}
}