use super::*;
use nalgebra::Rotation3;
fn opening(
center: (f64, f64, f64),
axis: Vector3<f64>,
depth: f64,
dir_sign: f64,
) -> ExtrudedSolidLike {
let z = Vector3::new(0.0, 0.0, 1.0);
let rot = Rotation3::rotation_between(&z, &axis)
.unwrap_or_else(Rotation3::identity)
.to_homogeneous();
let m = Matrix4::new_translation(&Vector3::new(center.0, center.1, center.2)) * rot;
let profile = Profile2D::new(vec![
Point2::new(-0.5, -0.5),
Point2::new(0.5, -0.5),
Point2::new(0.5, 0.5),
Point2::new(-0.5, 0.5),
]);
ExtrudedSolidLike {
profile,
depth,
dir_sign,
m,
}
}
const HZ_MIN: f64 = 0.0;
const HZ_MAX: f64 = 4.0;
fn host_axis() -> Vector3<f64> {
Vector3::new(0.0, 0.0, 1.0)
}
fn hm_inv() -> Matrix4<f64> {
Matrix4::identity()
}
#[test]
fn parallel_through_opening_is_eligible() {
let op = opening((1.0, 1.0, 0.0), host_axis(), HZ_MAX, 1.0);
let fp = opening_solid_footprint(&op, &hm_inv(), &host_axis(), HZ_MIN, HZ_MAX, 0.04);
assert!(
fp.is_some(),
"a parallel full-depth opening must be eligible"
);
assert_eq!(fp.unwrap().len(), 4);
}
#[test]
fn perpendicular_opening_defers() {
let op = opening((1.0, 1.0, 2.0), Vector3::new(1.0, 0.0, 0.0), 1.0, 1.0);
assert!(
opening_solid_footprint(&op, &hm_inv(), &host_axis(), HZ_MIN, HZ_MAX, 0.04).is_none(),
"a perpendicular opening must defer"
);
}
#[test]
fn partial_depth_opening_defers() {
let op = opening((1.0, 1.0, 0.0), host_axis(), 1.0, 1.0);
assert!(
opening_solid_footprint(&op, &hm_inv(), &host_axis(), HZ_MIN, HZ_MAX, 0.04).is_none(),
"a partial-depth opening must defer"
);
}
#[test]
fn near_parallel_oblique_opening_defers() {
let theta = 1.0_f64.to_radians();
let axis = Vector3::new(theta.sin(), 0.0, theta.cos());
let op = opening((1.0, 1.0, 0.5 * theta.sin()), axis, 4.0, 1.0);
assert!(
opening_solid_footprint(&op, &hm_inv(), &host_axis(), HZ_MIN, HZ_MAX, 0.04).is_none(),
"a near-parallel oblique opening must defer to the exact kernel"
);
}
#[test]
fn annular_opening_defers() {
let mut op = opening((1.0, 1.0, 0.0), host_axis(), HZ_MAX, 1.0);
op.profile.add_hole(vec![
Point2::new(-0.2, -0.2),
Point2::new(-0.2, 0.2),
Point2::new(0.2, 0.2),
Point2::new(0.2, -0.2),
]);
assert!(
opening_solid_footprint(&op, &hm_inv(), &host_axis(), HZ_MIN, HZ_MAX, 0.04).is_none(),
"an annular opening must defer"
);
}
#[test]
fn footprint_interior_gates_boundary_breach() {
let profile = Profile2D::new(vec![
Point2::new(0.0, 0.0),
Point2::new(10.0, 0.0),
Point2::new(10.0, 10.0),
Point2::new(0.0, 10.0),
]);
let interior = vec![
Point2::new(2.0, 2.0),
Point2::new(3.0, 2.0),
Point2::new(3.0, 3.0),
Point2::new(2.0, 3.0),
];
let breaching = vec![
Point2::new(-1.0, 2.0),
Point2::new(3.0, 2.0),
Point2::new(3.0, 3.0),
Point2::new(-1.0, 3.0),
];
assert!(footprint_interior(&interior, &profile));
assert!(!footprint_interior(&breaching, &profile));
}