collision/volume/aabb/
mod.rs1pub use self::aabb2::Aabb2;
9pub use self::aabb3::Aabb3;
10
11use std::cmp::{Ordering, PartialOrd};
12
13use cgmath::{BaseNum, Point2, Point3};
14use cgmath::prelude::*;
15
16use crate::traits::Bound;
17
18mod aabb2;
19mod aabb3;
20
21pub(crate) fn min<S: PartialOrd + Copy>(lhs: S, rhs: S) -> S {
22 match lhs.partial_cmp(&rhs) {
23 Some(Ordering::Less) | Some(Ordering::Equal) | None => lhs,
24 _ => rhs,
25 }
26}
27
28pub(crate) fn max<S: PartialOrd + Copy>(lhs: S, rhs: S) -> S {
29 match lhs.partial_cmp(&rhs) {
30 Some(Ordering::Greater) | Some(Ordering::Equal) | None => lhs,
31 _ => rhs,
32 }
33}
34
35pub trait MinMax {
37 fn min(a: Self, b: Self) -> Self;
39
40 fn max(a: Self, b: Self) -> Self;
42}
43
44impl<S: PartialOrd> MinMax for Point2<S>
45where
46 S: BaseNum,
47{
48 fn min(a: Point2<S>, b: Point2<S>) -> Point2<S> {
49 Point2::new(min(a.x, b.x), min(a.y, b.y))
50 }
51
52 fn max(a: Point2<S>, b: Point2<S>) -> Point2<S> {
53 Point2::new(max(a.x, b.x), max(a.y, b.y))
54 }
55}
56
57impl<S: PartialOrd> MinMax for Point3<S>
58where
59 S: BaseNum,
60{
61 fn min(a: Point3<S>, b: Point3<S>) -> Point3<S> {
62 Point3::new(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z))
63 }
64
65 fn max(a: Point3<S>, b: Point3<S>) -> Point3<S> {
66 Point3::new(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z))
67 }
68}
69
70pub trait Aabb: Sized {
72 type Scalar: BaseNum;
74
75 type Diff: VectorSpace<Scalar = Self::Scalar> + ElementWise + Array<Element = Self::Scalar>;
77
78 type Point: EuclideanSpace<Scalar = Self::Scalar, Diff = Self::Diff> + MinMax;
80
81 fn new(p1: Self::Point, p2: Self::Point) -> Self;
83
84 fn zero() -> Self {
86 let p = Self::Point::origin();
87 Self::new(p, p)
88 }
89
90 fn min(&self) -> Self::Point;
92
93 fn max(&self) -> Self::Point;
95
96 #[inline]
98 fn dim(&self) -> Self::Diff {
99 self.max() - self.min()
100 }
101
102 #[inline]
104 fn volume(&self) -> Self::Scalar {
105 self.dim().product()
106 }
107
108 #[inline]
110 fn center(&self) -> Self::Point {
111 let two = Self::Scalar::one() + Self::Scalar::one();
112 self.min() + self.dim() / two
113 }
114
115 fn grow(&self, p: Self::Point) -> Self {
117 Aabb::new(MinMax::min(self.min(), p), MinMax::max(self.max(), p))
118 }
119
120 #[inline]
122 fn add_v(&self, v: Self::Diff) -> Self {
123 Aabb::new(self.min() + v, self.max() + v)
124 }
125
126 fn add_margin(&self, margin: Self::Diff) -> Self;
128
129 #[inline]
131 fn mul_s(&self, s: Self::Scalar) -> Self {
132 Aabb::new(self.min() * s, self.max() * s)
133 }
134
135 fn mul_v(&self, v: Self::Diff) -> Self {
137 let min = Self::Point::from_vec(self.min().to_vec().mul_element_wise(v));
138 let max = Self::Point::from_vec(self.max().to_vec().mul_element_wise(v));
139 Aabb::new(min, max)
140 }
141
142 fn transform<T>(&self, transform: &T) -> Self
145 where
146 T: Transform<Self::Point>;
147}
148
149impl<A> Bound for A
150where
151 A: Aabb,
152 A::Point: EuclideanSpace,
153{
154 type Point = A::Point;
155
156 fn min_extent(&self) -> A::Point {
157 self.min()
158 }
159
160 fn max_extent(&self) -> A::Point {
161 self.max()
162 }
163
164 fn with_margin(&self, add: <A::Point as EuclideanSpace>::Diff) -> Self {
165 self.add_margin(add)
166 }
167
168 fn transform_volume<T>(&self, transform: &T) -> Self
169 where
170 T: Transform<Self::Point>,
171 {
172 self.transform(transform)
173 }
174
175 fn empty() -> Self {
176 A::zero()
177 }
178}