use super::*;
use crate::kernel::arrangement::box_mesh;
use crate::kernel::mesh_bridge::{subtract, tris_to_mesh};
fn area_facing(mesh: &Mesh, n: Vector3<f64>) -> f64 {
let p = |i: u32| {
let i = i as usize * 3;
Vector3::new(
mesh.positions[i] as f64,
mesh.positions[i + 1] as f64,
mesh.positions[i + 2] as f64,
)
};
mesh.indices
.chunks_exact(3)
.map(|t| {
let c = (p(t[1]) - p(t[0])).cross(&(p(t[2]) - p(t[0])));
let len = c.norm();
if len > 0.0 && (c / len - n).norm() < 1e-3 {
0.5 * len
} else {
0.0
}
})
.sum()
}
#[test]
fn a_small_opening_keeps_its_hole_on_a_large_face_4698() {
for unit in [1.0_f64, 1000.0] {
for (width, height) in [(2.0 * unit, 1.0 * unit), (20.0 * unit, 10.0 * unit)] {
let (thick, half) = (0.2 * unit, 0.05 * unit);
let wall = tris_to_mesh(&box_mesh([0.0, 0.0, 0.0], [width, thick, height]));
let (cx, cz) = (width / 2.0, height / 2.0);
let opening = tris_to_mesh(&box_mesh(
[cx - half, -2.5 * thick, cz - half],
[cx + half, 3.5 * thick, cz + half],
));
let cut = ClippingProcessor::with_unit_scale(1.0 / unit)
.consolidate(subtract(&wall, &opening));
let front = area_facing(&cut, Vector3::new(0.0, -1.0, 0.0));
let expected = width * height - 4.0 * half * half;
assert!(
(front - expected).abs() < 1.0e-4 * unit * unit,
"{width} x {height} wall (1 m = {unit} units): front face reads {front}, \
expected {expected}"
);
}
}
}
#[test]
fn ring_noise_needs_both_hairline_and_a_small_share_of_the_plane_4698() {
use nalgebra::Point2;
let rect = |w: f64, h: f64| {
vec![Point2::new(0.0, 0.0), Point2::new(w, 0.0), Point2::new(w, h), Point2::new(0.0, h)]
};
for unit in [1.0_f64, 1000.0] {
let facade = 200.0 * unit * unit;
let u = |m: f64| m * unit;
assert!(
!ring_is_noise(&rect(u(0.1), u(0.1)), facade, 1.0 / unit),
"a 10 cm opening on a 200 m² face is geometry (1 m = {unit} units)"
);
assert!(
ring_is_noise(&rect(u(1.0), u(50.0e-6)), facade, 1.0 / unit),
"a 50 µm sliver on a 200 m² face is noise (1 m = {unit} units)"
);
assert!(
!ring_is_noise(&rect(u(1.0), u(0.001)), facade, 1.0 / unit),
"a 1 mm strip is over the physical noise threshold (1 m = {unit} units)"
);
let lip = rect(u(2.35), u(1.67e-6));
assert!(
!ring_is_noise(&lip, u(2.35) * u(1.67e-6), 1.0 / unit),
"a reveal lip that is its whole plane is kept (1 m = {unit} units)"
);
}
assert!(
ring_is_noise(&rect(5.0e-5, 5.0e-5), 200.0, 1.0),
"a 50 µm speck in metres is noise"
);
assert!(ring_is_noise(&rect(5.0e-2, 5.0e-2), 2.0e8, 0.001));
assert!(ring_is_noise(&rect(5.0e-5, 5.0e-5), 2.5e-9, 1.0));
assert!(!ring_is_noise(&rect(5.0e-2, 5.0e-2), 2.5e-3, 0.001));
}