use super::{operand_extent, point_inside, ray_dir, sound_far};
use crate::kernel::arrangement::box_mesh;
#[test]
fn the_extended_endpoint_clears_the_box_for_any_direction_sign() {
let bb = ([-2.0, -1.0, -3.0], [4.0, 5.0, 6.0]);
let (lo, hi) = bb;
let inside = |q: [f64; 3]| (0..3).all(|i| q[i] >= lo[i] && q[i] <= hi[i]);
let base = ray_dir();
let mut dirs = vec![base];
for mask in 1..8u8 {
let mut d = base;
for (i, c) in d.iter_mut().enumerate() {
if mask & (1 << i) != 0 {
*c = -*c;
}
}
dirs.push(d);
}
dirs.push([1.0, 0.0, 0.0]);
dirs.push([0.0, -1.0, 0.0]);
let starts = [
[0.0, 0.0, 0.0],
[-1.9, -0.9, -2.9],
[3.9, 4.9, 5.9],
[1.0, -0.5, 2.0],
];
for d in &dirs {
for p in &starts {
for far_l in [3.0, 13.0, 1.0e6] {
let q = sound_far(*p, *d, far_l, bb);
assert!(
q.iter().all(|v| v.is_finite()),
"endpoint must stay finite: dir={d:?} p={p:?} far_l={far_l} q={q:?}"
);
assert!(
!inside(q),
"endpoint must clear the box: dir={d:?} p={p:?} far_l={far_l} q={q:?}"
);
}
}
}
}
#[test]
fn an_endpoint_already_outside_the_box_is_returned_unchanged() {
let bb = ([-2.0, -1.0, -3.0], [4.0, 5.0, 6.0]);
let d = ray_dir();
let p = [-50.0, -50.0, -50.0];
let far_l = 4.0; let plain = [p[0] + d[0] * far_l, p[1] + d[1] * far_l, p[2] + d[2] * far_l];
assert_eq!(sound_far(p, d, far_l, bb).map(f64::to_bits), plain.map(f64::to_bits));
}
struct Rng(u64);
impl Rng {
fn next_u64(&mut self) -> u64 {
self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = self.0;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
fn f(&mut self, lo: f64, hi: f64) -> f64 {
let u = (self.next_u64() >> 11) as f64 / (1u64 << 53) as f64;
lo + u * (hi - lo)
}
}
#[test]
fn the_parity_predicate_matches_an_analytic_box_oracle() {
const N: usize = 120_000;
let mut rng = Rng(0x5EED_1234);
let (mut wrong_inside, mut wrong_outside) = (0usize, 0usize);
let mut examples: Vec<String> = Vec::new();
for _ in 0..N {
let lo = [rng.f(-6.5, 0.6), rng.f(-6.5, 0.6), rng.f(-6.5, 0.6)];
let hi = [
lo[0] + rng.f(0.15, 5.0),
lo[1] + rng.f(0.15, 5.0),
lo[2] + rng.f(0.15, 5.0),
];
let tris = box_mesh(lo, hi);
let far_l = operand_extent(&tris);
let p = [
rng.f(lo[0] - 6.0, hi[0] + 2.0),
rng.f(lo[1] - 6.0, hi[1] + 2.0),
rng.f(lo[2] - 6.0, hi[2] + 2.0),
];
if (0..3).any(|i| (p[i] - lo[i]).abs() < 1.0e-9 || (p[i] - hi[i]).abs() < 1.0e-9) {
continue;
}
let truth = (0..3).all(|i| p[i] > lo[i] && p[i] < hi[i]);
let got = point_inside(p, &tris, far_l, (lo, hi));
if got != truth {
if got {
wrong_inside += 1;
} else {
wrong_outside += 1;
}
if examples.len() < 3 {
examples.push(format!("p={p:?} box=[{lo:?},{hi:?}] truth={truth} got={got}"));
}
}
}
assert!(
wrong_inside == 0 && wrong_outside == 0,
"the parity predicate must agree with the analytic oracle: {wrong_inside} \
false-inside, {wrong_outside} false-outside in {N} queries\n {}",
examples.join("\n ")
);
}
#[test]
fn a_superset_aabb_matches_the_exact_box_and_a_shrunk_one_does_not() {
let lo = [-1.0, -0.3, -2.0];
let hi = [3.0, 0.6, 1.0];
let tris = box_mesh(lo, hi);
let exact: super::Aabb = (lo, hi);
let eps = 1.0e-7;
let points: Vec<[f64; 3]> = vec![
[hi[0], 0.1, -0.5], [hi[0] + eps, 0.1, -0.5], [lo[0], 0.1, -0.5], [lo[0] - eps, 0.1, -0.5], [1.0, hi[1], -0.5], [1.0, hi[1] + eps, -0.5], [1.0, lo[1] - eps, -0.5], [1.0, 0.1, hi[2]], [1.0, 0.1, hi[2] + eps], [1.0, 0.1, lo[2] - eps], [1.0, 0.1, -0.5], [50.0, 50.0, 50.0], [-50.0, -50.0, -50.0], ];
let far_ls = [2.0, 3.0, operand_extent(&tris)];
for &far_l in &far_ls {
for &pad in &[0.0, 1.0e-4, 0.05, 0.3] {
let padded: super::Aabb =
([lo[0] - pad, lo[1] - pad, lo[2] - pad], [hi[0] + pad, hi[1] + pad, hi[2] + pad]);
for &p in &points {
let want = point_inside(p, &tris, far_l, exact);
let got = point_inside(p, &tris, far_l, padded);
assert_eq!(
got, want,
"padded box changed the verdict at p={p:?}, far_l={far_l}, pad={pad}: \
exact-box={want} padded-box={got}"
);
}
}
}
let dir = ray_dir();
let far_l = 2.0; let eps_in = 1.0e-3; let shrink = 0.05; assert!(eps_in < shrink, "far0 must land outside the shrunk box on Y");
let far0 = [(lo[0] + hi[0]) / 2.0, hi[1] - eps_in, (lo[2] + hi[2]) / 2.0];
let p = [far0[0] - dir[0] * far_l, far0[1] - dir[1] * far_l, far0[2] - dir[2] * far_l];
assert!(
(0..3).all(|i| far0[i] >= lo[i] && far0[i] <= hi[i]),
"far0={far0:?} must be inside the exact box [{lo:?},{hi:?}]"
);
assert!(p[1] < lo[1], "p={p:?} must be strictly outside the box on Y (below lo[1]={})", lo[1]);
let shrunk: super::Aabb =
([lo[0] + shrink, lo[1] + shrink, lo[2] + shrink], [hi[0] - shrink, hi[1] - shrink, hi[2] - shrink]);
assert!(
far0[1] > shrunk.1[1],
"far0={far0:?} must land outside the shrunk box's +Y face at {}",
shrunk.1[1]
);
let exact_verdict = point_inside(p, &tris, far_l, exact);
let shrunk_verdict = point_inside(p, &tris, far_l, shrunk);
assert_ne!(
exact_verdict, shrunk_verdict,
"expected the shrunk box to flip the verdict at p={p:?}, far_l={far_l}: \
exact-box={exact_verdict} shrunk-box={shrunk_verdict} — if they agree, \
`point_inside` may not actually be using its `aabb` argument, which would \
make the superset-safety assertions above vacuous"
);
assert!(!exact_verdict, "exact-box verdict for an exterior p should be `outside`");
}