forked from 1b-agent/opencadstudio-upstream
fix: solve perpendicular placement in kernel
This commit is contained in:
1 parent
b546f9b161
commit
b6478b3b89
5 files changed
+61
-88
No files matched your search
Generated
+2
-2
@@ -921,7 +921,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||
[[package]]
|
||||
name = "cadkernel"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=35aa7a5#35aa7a541ab7c020cd23f43978373337523e25df"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=7e43598#7e435984d9ba32999d2471930c18449a2ab58d67"
|
||||
dependencies = [
|
||||
"acadrust",
|
||||
"cavalier_contours",
|
||||
@@ -932,7 +932,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cadkernel-constraints"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=35aa7a5#35aa7a541ab7c020cd23f43978373337523e25df"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git?rev=7e43598#7e435984d9ba32999d2471930c18449a2ab58d67"
|
||||
dependencies = [
|
||||
"nalgebra",
|
||||
]
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ clap = { version = "4", features = ["derive", "string"] }
|
||||
env_logger = "0.11"
|
||||
log = "0.4"
|
||||
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "8a28c21", features = ["serde"] }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "35aa7a5", features = ["acis", "offset"] }
|
||||
cadkernel-constraints = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "35aa7a5" }
|
||||
cadkernel = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "7e43598", features = ["acis", "offset"] }
|
||||
cadkernel-constraints = { git = "https://github.com/HakanSeven12/cadkernel.git", rev = "7e43598" }
|
||||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||
flate2 = "1"
|
||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
||||
|
||||
+35
-57
@@ -3266,62 +3266,6 @@ impl OpenCADStudio {
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.record_undo_parametric_constraints_before(scope, constraints_before);
|
||||
if first.entity != second.entity {
|
||||
use crate::scene::parametric_constraints::directional_reference_endpoints;
|
||||
|
||||
let fixed_axis = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity(first.entity)
|
||||
.and_then(|entity| directional_reference_endpoints(entity, first));
|
||||
let moving_axis = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity(second.entity)
|
||||
.and_then(|entity| directional_reference_endpoints(entity, second));
|
||||
if let (Some([fixed_start, fixed_end]), Some([moving_start, moving_end])) =
|
||||
(fixed_axis, moving_axis)
|
||||
{
|
||||
let fixed_direction = fixed_end - fixed_start;
|
||||
let moving_direction = moving_end - moving_start;
|
||||
if fixed_direction.length_squared() > 1.0e-24
|
||||
&& moving_direction.length_squared() > 1.0e-24
|
||||
{
|
||||
let fixed_angle = fixed_direction.y.atan2(fixed_direction.x);
|
||||
let moving_angle = moving_direction.y.atan2(moving_direction.x);
|
||||
let normalize = |angle: f64| {
|
||||
(angle + std::f64::consts::PI)
|
||||
.rem_euclid(std::f64::consts::TAU)
|
||||
- std::f64::consts::PI
|
||||
};
|
||||
let positive = normalize(
|
||||
fixed_angle + std::f64::consts::FRAC_PI_2 - moving_angle,
|
||||
);
|
||||
let negative = normalize(
|
||||
fixed_angle - std::f64::consts::FRAC_PI_2 - moving_angle,
|
||||
);
|
||||
let angle_rad = if positive.abs() <= negative.abs() {
|
||||
positive
|
||||
} else {
|
||||
negative
|
||||
};
|
||||
if angle_rad.abs() > 1.0e-12 {
|
||||
self.tabs[i].scene.transform_entities(
|
||||
&[second.entity],
|
||||
&crate::command::EntityTransform::Rotate {
|
||||
center: glam::DVec3::new(
|
||||
moving_start.x,
|
||||
moving_start.y,
|
||||
moving_start.z,
|
||||
),
|
||||
axis: glam::DVec3::Z,
|
||||
angle_rad,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let id = self.tabs[i].scene.parametric_constraint_set_mut(scope).add(
|
||||
ConstraintKind::Perpendicular,
|
||||
refs,
|
||||
@@ -3336,7 +3280,7 @@ impl OpenCADStudio {
|
||||
.into_iter()
|
||||
.map(|handle| (handle, crate::scene::ChangeKind::Modified))
|
||||
.collect::<Vec<_>>();
|
||||
self.tabs[i].scene.bump_entities_with_parametric_policy(
|
||||
self.tabs[i].scene.bump_entities_with_initial_parametric_policy(
|
||||
&changes,
|
||||
&[first_fixed, second_start],
|
||||
true,
|
||||
@@ -8506,6 +8450,40 @@ mod parametric_constraint_undo_tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn perpendicular_initial_solve_rotates_parallel_second_line_in_kernel() {
|
||||
let mut app = OpenCADStudio::new_for_test();
|
||||
let _ = app.automation_op(r#"{"op":"new"}"#);
|
||||
let first = add_line(&mut app, 0.0, 0.0, 10.0, 0.0);
|
||||
let second = add_line(&mut app, 20.0, 0.0, 30.0, 0.0);
|
||||
|
||||
let _ = app.apply_cmd_result(CmdResult::AddPerpendicularConstraint {
|
||||
first: ParametricRef::whole(first),
|
||||
second: ParametricRef::whole(second),
|
||||
first_fixed: ParametricRef::whole(first),
|
||||
second_start: ParametricRef::point(second, 0),
|
||||
label: "Perpendicular constraint",
|
||||
});
|
||||
|
||||
let line = |handle| match app.tabs[app.active_tab].scene.document.get_entity(handle) {
|
||||
Some(acadrust::EntityType::Line(line)) => line.clone(),
|
||||
other => panic!("expected a Line, got {other:?}"),
|
||||
};
|
||||
let fixed = line(first);
|
||||
let moving = line(second);
|
||||
assert_eq!(fixed.start, acadrust::types::Vector3::new(0.0, 0.0, 0.0));
|
||||
assert_eq!(fixed.end, acadrust::types::Vector3::new(10.0, 0.0, 0.0));
|
||||
assert!((moving.start - acadrust::types::Vector3::new(20.0, 0.0, 0.0)).length() < 1.0e-9);
|
||||
assert!((moving.length() - 10.0).abs() < 1.0e-7);
|
||||
assert!(
|
||||
(fixed.end - fixed.start)
|
||||
.dot(&(moving.end - moving.start))
|
||||
.abs()
|
||||
< 1.0e-7,
|
||||
"fixed={fixed:?}, moving={moving:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// Drawing commands must not create parametric constraints implicitly.
|
||||
#[test]
|
||||
fn drawing_a_line_onto_an_existing_endpoint_does_not_add_a_constraint() {
|
||||
|
||||
@@ -234,4 +234,26 @@ mod tests {
|
||||
assert_eq!(first_fixed, ParametricRef::whole(first));
|
||||
assert_eq!(second_start, ParametricRef::point(second, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preselection_uses_the_first_straight_polyline_segment() {
|
||||
let handle = Handle::new(11);
|
||||
let mut polyline = acadrust::entities::LwPolyline::new();
|
||||
polyline.vertices = vec![
|
||||
acadrust::entities::LwVertex::with_bulge(
|
||||
acadrust::types::Vector2::new(0.0, 0.0),
|
||||
1.0,
|
||||
),
|
||||
acadrust::entities::LwVertex::from_coords(4.0, 0.0),
|
||||
acadrust::entities::LwVertex::from_coords(8.0, 0.0),
|
||||
];
|
||||
|
||||
let pick = PerpendicularConstraintCommand::preselected_reference(
|
||||
&EntityType::LwPolyline(polyline),
|
||||
handle,
|
||||
)
|
||||
.expect("straight segment");
|
||||
assert_eq!(pick.reference, ParametricRef::segment(handle, 1));
|
||||
assert_eq!(pick.start_reference, ParametricRef::point(handle, 1));
|
||||
}
|
||||
}
|
||||
@@ -186,33 +186,6 @@ 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(
|
||||
|
||||
Reference in new issue
Block a user