forked from 1b-agent/opencadstudio-upstream
fix: preserve selected smooth curve geometry
This commit is contained in:
1 parent
76451f7298
commit
e8125c8702
5 files changed
+157
-4
No files matched your search
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user