1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//!
//! `flat_spatial` is a crate dedicated to spatial partitioning structures that are not based on trees
//! (which are recursive) but on simple flat structures such as grids.
//!
//! `Grid` partitions the space using cells of user defined width.
//! `AABBGrid` partitions the space using cells too, but stores Axis-Aligned Bounding Boxes.
//!
//! Check `Grid` and `AABBGrid` docs for more information.
//!

pub mod cell;
pub mod grid;
pub mod aabbgrid;
pub mod storage;

pub use grid::Grid;
pub use aabbgrid::AABBGrid;

pub trait Vec2: From<[f32; 2]> + Copy {
    fn x(&self) -> f32;
    fn y(&self) -> f32;
}

pub trait AABB: Copy {
    type V2: Vec2;

    fn ll(&self) -> Self::V2;
    fn ur(&self) -> Self::V2;

    #[inline]
    fn intersects(&self, b: &Self) -> bool {
        let ll = self.ll();
        let ur = self.ur();

        let bll = b.ll();
        let bur = b.ur();

        let x = f32::abs((ll.x() + ur.x()) - (bll.x() + bur.x()))
            <= (ur.x() - ll.x() + bur.x() - bll.x());
        let y = f32::abs((ll.y() + ur.y()) - (bll.y() + bur.y()))
            <= (ur.y() - ll.y() + bur.y() - bll.y());

        x & y
    }
}

impl Vec2 for [f32; 2] {
    #[inline]
    fn x(&self) -> f32 {
        unsafe { *self.get_unchecked(0) }
    }

    #[inline]
    fn y(&self) -> f32 {
        unsafe { *self.get_unchecked(1) }
    }
}

#[cfg(feature = "euclid")]
mod euclid_impl {
    use super::Vec2;
    use super::AABB;
    use euclid::{Point2D, Vector2D};

    impl<U> Vec2 for Point2D<f32, U> {
        fn x(&self) -> f32 {
            self.x
        }
        fn y(&self) -> f32 {
            self.y
        }
    }

    impl<U> Vec2 for Vector2D<f32, U> {
        fn x(&self) -> f32 {
            self.x
        }
        fn y(&self) -> f32 {
            self.y
        }
    }

    impl<U> AABB for euclid::Rect<f32, U> {
        type V2 = Point2D<f32, U>;
        fn ll(&self) -> Self::V2 {
            self.origin
        }
        fn ur(&self) -> Self::V2 {
            self.origin + self.size
        }
    }
}

#[cfg(feature = "parry2d")]
mod parry2d_impl {
    use super::Vec2;
    use super::AABB as AABBTrait;
    use parry2d::bounding_volume::Aabb;
    use parry2d::math::{Point, Vector};

    impl Vec2 for Point<f32> {
        fn x(&self) -> f32 {
            self.x
        }
        fn y(&self) -> f32 {
            self.y
        }
    }

    impl Vec2 for Vector<f32> {
        fn x(&self) -> f32 {
            self.x
        }
        fn y(&self) -> f32 {
            self.y
        }
    }

    impl AABBTrait for Aabb {
        type V2 = Point<f32>;
        fn ll(&self) -> Self::V2 {
            self.mins
        }
        fn ur(&self) -> Self::V2 {
            self.maxs
        }
    }
}