use crate::aabb::aabb_ray_cast;
use crate::math_functions::{aabb_contains, aabb_overlaps, is_valid_aabb, Aabb, Vec2};
fn ensure_small(value: f32, tolerance: f32) {
assert!(
!(value < -tolerance || tolerance < value),
"|{value}| > tolerance {tolerance}"
);
}
fn aabb(lx: f32, ly: f32, ux: f32, uy: f32) -> Aabb {
Aabb {
lower_bound: Vec2 { x: lx, y: ly },
upper_bound: Vec2 { x: ux, y: uy },
}
}
#[test]
fn aabb_validity_overlap_contains() {
let mut a = aabb(-1.0, -1.0, -2.0, -2.0);
assert!(!is_valid_aabb(a));
a.upper_bound = Vec2 { x: 1.0, y: 1.0 };
assert!(is_valid_aabb(a));
let b = aabb(2.0, 2.0, 4.0, 4.0);
assert!(!aabb_overlaps(a, b));
assert!(!aabb_contains(a, b));
}
#[test]
fn aabb_ray_cast_cases() {
let a = aabb(-1.0, -1.0, 1.0, 1.0);
let eps = f32::EPSILON;
let v = |x, y| Vec2 { x, y };
let o = aabb_ray_cast(a, v(-3.0, 0.0), v(3.0, 0.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0 / 3.0, eps);
ensure_small(o.normal.x + 1.0, eps);
ensure_small(o.normal.y, eps);
ensure_small(o.point.x + 1.0, eps);
ensure_small(o.point.y, eps);
let o = aabb_ray_cast(a, v(3.0, 0.0), v(-3.0, 0.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0 / 3.0, eps);
ensure_small(o.normal.x - 1.0, eps);
ensure_small(o.normal.y, eps);
ensure_small(o.point.x - 1.0, eps);
ensure_small(o.point.y, eps);
let o = aabb_ray_cast(a, v(0.0, -3.0), v(0.0, 3.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0 / 3.0, eps);
ensure_small(o.normal.x, eps);
ensure_small(o.normal.y + 1.0, eps);
ensure_small(o.point.x, eps);
ensure_small(o.point.y + 1.0, eps);
let o = aabb_ray_cast(a, v(0.0, 3.0), v(0.0, -3.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0 / 3.0, eps);
ensure_small(o.normal.x, eps);
ensure_small(o.normal.y - 1.0, eps);
ensure_small(o.point.x, eps);
ensure_small(o.point.y - 1.0, eps);
assert!(!aabb_ray_cast(a, v(-3.0, 2.0), v(3.0, 2.0)).hit);
assert!(!aabb_ray_cast(a, v(2.0, -3.0), v(2.0, 3.0)).hit);
assert!(!aabb_ray_cast(a, v(0.0, 0.0), v(2.0, 0.0)).hit);
let o = aabb_ray_cast(a, v(-2.0, -2.0), v(2.0, 2.0));
assert!(o.hit);
ensure_small(o.fraction - 0.25, eps);
assert!((o.normal.x == -1.0 && o.normal.y == 0.0) || (o.normal.x == 0.0 && o.normal.y == -1.0));
assert!(!aabb_ray_cast(a, v(-2.0, 1.5), v(2.0, 1.5)).hit);
let o = aabb_ray_cast(a, v(-2.0, 1.0), v(2.0, 1.0));
assert!(o.hit);
ensure_small(o.fraction - 0.25, eps);
ensure_small(o.normal.x + 1.0, eps);
ensure_small(o.normal.y, eps);
assert!(!aabb_ray_cast(a, v(-3.0, 0.0), v(-2.5, 0.0)).hit);
assert!(!aabb_ray_cast(a, v(0.0, 0.0), v(0.0, 0.0)).hit);
let o = aabb_ray_cast(a, v(-2.0, 0.0), v(-1.0, 0.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0, eps);
ensure_small(o.normal.x + 1.0, eps);
ensure_small(o.normal.y, eps);
let offset_aabb = aabb(2.0, 3.0, 4.0, 5.0);
let o = aabb_ray_cast(offset_aabb, v(0.0, 4.0), v(6.0, 4.0));
assert!(o.hit);
ensure_small(o.fraction - 1.0 / 3.0, eps);
ensure_small(o.normal.x + 1.0, eps);
ensure_small(o.normal.y, eps);
ensure_small(o.point.x - 2.0, eps);
ensure_small(o.point.y - 4.0, eps);
}