use num_traits::{Bounded, Num, NumCast};
pub trait IndexableNum: Copy + Num + PartialOrd + Default + Bounded + NumCast {
#[inline]
fn min(self, other: Self) -> Self {
if self < other {
return self;
}
other
}
#[inline]
fn max(self, other: Self) -> Self {
if self > other {
return self;
}
other
}
}
impl IndexableNum for u16 {}
impl IndexableNum for i32 {}
impl IndexableNum for u32 {}
impl IndexableNum for i64 {}
impl IndexableNum for u64 {}
impl IndexableNum for i128 {}
impl IndexableNum for u128 {}
impl IndexableNum for f32 {}
impl IndexableNum for f64 {}
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AABB<T = f64> {
pub min_x: T,
pub min_y: T,
pub max_x: T,
pub max_y: T,
}
impl<T> Default for AABB<T>
where
T: IndexableNum,
{
#[inline]
fn default() -> Self {
AABB {
min_x: T::zero(),
min_y: T::zero(),
max_x: T::zero(),
max_y: T::zero(),
}
}
}
impl<T> AABB<T>
where
T: IndexableNum,
{
#[inline]
pub fn new(min_x: T, min_y: T, max_x: T, max_y: T) -> AABB<T> {
AABB {
min_x,
min_y,
max_x,
max_y,
}
}
#[inline]
pub fn overlaps_aabb(&self, other: &AABB<T>) -> bool {
self.overlaps(other.min_x, other.min_y, other.max_x, other.max_y)
}
#[inline]
pub fn overlaps(&self, min_x: T, min_y: T, max_x: T, max_y: T) -> bool {
if self.max_x < min_x || self.max_y < min_y || self.min_x > max_x || self.min_y > max_y {
return false;
}
true
}
#[inline]
pub fn contains_aabb(&self, other: &AABB<T>) -> bool {
self.contains(other.min_x, other.min_y, other.max_x, other.max_y)
}
#[inline]
pub fn contains(&self, min_x: T, min_y: T, max_x: T, max_y: T) -> bool {
self.min_x <= min_x && self.min_y <= min_y && self.max_x >= max_x && self.max_y >= max_y
}
}
#[derive(Debug)]
pub enum Control<B> {
Continue,
Break(B),
}
impl<B> Default for Control<B> {
fn default() -> Self {
Control::Continue
}
}
pub trait ControlFlow {
fn continuing() -> Self;
fn should_break(&self) -> bool;
}
impl<B> ControlFlow for Control<B> {
#[inline]
fn continuing() -> Self {
Control::Continue
}
#[inline]
fn should_break(&self) -> bool {
matches!(*self, Control::Break(_))
}
}
impl ControlFlow for () {
#[inline]
fn continuing() -> Self {}
#[inline]
fn should_break(&self) -> bool {
false
}
}
impl<C, E> ControlFlow for Result<C, E>
where
C: ControlFlow,
{
fn continuing() -> Self {
Ok(C::continuing())
}
fn should_break(&self) -> bool {
matches!(self, Err(_))
}
}
pub trait QueryVisitor<T, C>
where
T: IndexableNum,
C: ControlFlow,
{
fn visit(&mut self, index_pos: usize) -> C;
}
impl<T, C, F> QueryVisitor<T, C> for F
where
T: IndexableNum,
C: ControlFlow,
F: FnMut(usize) -> C,
{
#[inline]
fn visit(&mut self, index_pos: usize) -> C {
self(index_pos)
}
}
pub trait NeighborVisitor<T, C>
where
T: IndexableNum,
C: ControlFlow,
{
fn visit(&mut self, index_pos: usize, dist_squared: T) -> C;
}
impl<T, C, F> NeighborVisitor<T, C> for F
where
T: IndexableNum,
C: ControlFlow,
F: FnMut(usize, T) -> C,
{
#[inline]
fn visit(&mut self, index_pos: usize, dist_squared: T) -> C {
self(index_pos, dist_squared)
}
}
#[macro_export]
macro_rules! try_control {
($e:expr) => {
match $e {
x => {
if x.should_break() {
return x;
}
}
}
};
}