forked from 1b-agent/opencadstudio-upstream
feat(ucs): align UCS Face origin and axes to nearest vertex and edge
This commit is contained in:
1 parent
6840687f32
commit
973d7b0bb6
3 files changed
+191
-7
No files matched your search
@@ -105,3 +105,74 @@ fn ucs_pick_command_enables_solid_face_picking() {
|
||||
_ => panic!("Expected CmdResult::Dispatch"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autocad_style_face_ucs_snaps_origin_and_aligns_axes_on_box() {
|
||||
let box_body = solid_model::box_solid([0.0, 0.0, 0.0], 10.0, 20.0, 30.0)
|
||||
.expect("box_solid constructs successfully");
|
||||
|
||||
// Top face is at Z = +15, bounds X in [-5, 5], Y in [-10, 10].
|
||||
// Pick near corner (5, 10, 15), closer to the edge along -X than the edge along -Y.
|
||||
let face = solid_model::nearest_planar_face(&box_body, [3.0, 9.0, 15.0])
|
||||
.expect("top face found");
|
||||
let ucs = solid_model::planar_face_ucs(&box_body, face, [3.0, 9.0, 15.0])
|
||||
.expect("planar_face_ucs constructed");
|
||||
|
||||
// Origin must snap to the nearest corner (5, 10, 15) instead of the pick coordinate.
|
||||
assert!((ucs.origin.x - 5.0).abs() < 1e-6);
|
||||
assert!((ucs.origin.y - 10.0).abs() < 1e-6);
|
||||
assert!((ucs.origin.z - 15.0).abs() < 1e-6);
|
||||
|
||||
// Z axis must be outward normal (0, 0, 1).
|
||||
let z = glam::DVec3::new(ucs.x_axis.x, ucs.x_axis.y, ucs.x_axis.z)
|
||||
.cross(glam::DVec3::new(ucs.y_axis.x, ucs.y_axis.y, ucs.y_axis.z));
|
||||
assert!((z.z - 1.0).abs() < 1e-6);
|
||||
|
||||
// Closer to edge along -X: X axis must point along (-1, 0, 0).
|
||||
assert!((ucs.x_axis.x - (-1.0)).abs() < 1e-6);
|
||||
assert!(ucs.x_axis.y.abs() < 1e-6);
|
||||
assert!(ucs.x_axis.z.abs() < 1e-6);
|
||||
|
||||
// Y axis = Z x X = (0, 0, 1) x (-1, 0, 0) = (0, -1, 0).
|
||||
assert!(ucs.y_axis.x.abs() < 1e-6);
|
||||
assert!((ucs.y_axis.y - (-1.0)).abs() < 1e-6);
|
||||
assert!(ucs.y_axis.z.abs() < 1e-6);
|
||||
|
||||
// Now pick near the same corner (5, 10, 15), but closer to the edge along -Y.
|
||||
let ucs_y_edge = solid_model::planar_face_ucs(&box_body, face, [4.5, 7.0, 15.0])
|
||||
.expect("planar_face_ucs constructed");
|
||||
|
||||
// Origin is still the same corner (5, 10, 15).
|
||||
assert!((ucs_y_edge.origin.x - 5.0).abs() < 1e-6);
|
||||
assert!((ucs_y_edge.origin.y - 10.0).abs() < 1e-6);
|
||||
assert!((ucs_y_edge.origin.z - 15.0).abs() < 1e-6);
|
||||
|
||||
// Closer to edge along -Y: X axis must point along (0, -1, 0).
|
||||
assert!(ucs_y_edge.x_axis.x.abs() < 1e-6);
|
||||
assert!((ucs_y_edge.x_axis.y - (-1.0)).abs() < 1e-6);
|
||||
assert!(ucs_y_edge.x_axis.z.abs() < 1e-6);
|
||||
|
||||
// Y axis = Z x X = (0, 0, 1) x (0, -1, 0) = (1, 0, 0).
|
||||
assert!((ucs_y_edge.y_axis.x - 1.0).abs() < 1e-6);
|
||||
assert!(ucs_y_edge.y_axis.y.abs() < 1e-6);
|
||||
assert!(ucs_y_edge.y_axis.z.abs() < 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autocad_style_face_ucs_on_puck() {
|
||||
let body = puck();
|
||||
let top_face = solid_model::nearest_planar_face(&body, [60.0, -25.0, 10.0]).unwrap();
|
||||
let ucs = solid_model::planar_face_ucs(&body, top_face, [60.0, -25.0, 10.0]).unwrap();
|
||||
|
||||
// Normal Z = (0, 0, 1).
|
||||
let z = glam::DVec3::new(ucs.x_axis.x, ucs.x_axis.y, ucs.x_axis.z)
|
||||
.cross(glam::DVec3::new(ucs.y_axis.x, ucs.y_axis.y, ucs.y_axis.z));
|
||||
assert!((z.z - 1.0).abs() < 1e-6);
|
||||
|
||||
// Orthonormality of X and Y.
|
||||
let x = glam::DVec3::new(ucs.x_axis.x, ucs.x_axis.y, ucs.x_axis.z);
|
||||
let y = glam::DVec3::new(ucs.y_axis.x, ucs.y_axis.y, ucs.y_axis.z);
|
||||
assert!((x.length() - 1.0).abs() < 1e-6);
|
||||
assert!((y.length() - 1.0).abs() < 1e-6);
|
||||
assert!(x.dot(y).abs() < 1e-6);
|
||||
}
|
||||
Reference in new issue
Block a user