Gamedev Framework (gf)  0.12.0
A C++14 framework for 2D games
Box.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2019 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * Part of this file comes from SFML, with the same license:
22  * Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
23  */
24 #ifndef GF_BOX_H
25 #define GF_BOX_H
26 
27 #include <cstddef>
28 #include <algorithm>
29 #include <limits>
30 #include <tuple>
31 
32 #include "Portability.h"
33 #include "Vector.h"
34 #include "VectorOps.h"
35 
36 namespace gf {
37 #ifndef DOXYGEN_SHOULD_SKIP_THIS
38 inline namespace v1 {
39 #endif
40 
47  template<typename T, std::size_t N>
48  struct Box {
51 
52  constexpr Box() noexcept
53  {
54  for (std::size_t i = 0; i < N; ++i) {
55  min[i] = std::numeric_limits<T>::max();
56  max[i] = std::numeric_limits<T>::lowest();
57  }
58  }
59 
60  constexpr Box(Vector<T, N> p0, Vector<T, N> p1) noexcept
61  {
62  for (std::size_t i = 0; i < N; ++i) {
63  std::tie(min[i], max[i]) = std::minmax(p0[i], p1[i]);
64  }
65  }
66 
67  constexpr Box(const T (&p0)[N], const T (&p1)[N]) noexcept {
68  for (std::size_t i = 0; i < N; ++i) {
69  std::tie(min[i], max[i]) = std::minmax(p0[i], p1[i]);
70  }
71  }
72 
73  constexpr explicit Box(Vector<T, N> p) noexcept
74  : min(p)
75  , max(p)
76  {
77 
78  }
79 
80  constexpr Vector<T, N> getSize() const noexcept {
81  return max - min;
82  }
83 
84  constexpr bool isEmpty() const noexcept {
85  for (std::size_t i = 0; i < N; ++i) {
86  if (min[i] >= max[i]) {
87  return true;
88  }
89  }
90 
91  return false;
92  }
93 
94  constexpr Vector<T, N> getCenter() const noexcept {
95  return (min + max) / 2;
96  }
97 
98  constexpr bool contains(Vector<T, N> point) const noexcept {
99  for (std::size_t i = 0; i < N; ++i) {
100  if (!(min[i] <= point[i] && point[i] <= max[i])) {
101  return false;
102  }
103  }
104 
105  return true;
106  }
107 
108  constexpr bool contains(const Box<T, N>& other) const noexcept {
109  for (std::size_t i = 0; i < N; ++i) {
110  if (!(min[i] <= other.min[i] && other.max[i] <= max[i])) {
111  return false;
112  }
113  }
114 
115  return true;
116  }
117 
118  constexpr bool intersects(const Box<T, N>& other) const noexcept {
119  for (std::size_t i = 0; i < N; ++i) {
120  if (!(min[i] < other.max[i] && other.min[i] < max[i])) {
121  return false;
122  }
123  }
124 
125  return true;
126  }
127 
128  Box<T, N> getIntersection(const Box<T, N>& other) const noexcept {
129  Box<T, N> res;
130 
131  for (std::size_t i = 0; i < N; ++i) {
132  res.min[i] = std::max(min[i], other.min[i]);
133  res.max[i] = std::min(max[i], other.max[i]);
134  }
135 
136  return res;
137  }
138 
139  T getIntersectionVolume(const Box<T, N>& other) const noexcept {
140  T res = 1;
141 
142  for (std::size_t i = 0; i < N; ++i) {
143  auto axisMin = std::max(min[i], other.min[i]);
144  auto axisMax = std::min(max[i], other.max[i]);
145 
146  if (axisMin >= axisMax) {
147  return T();
148  }
149 
150  res *= (axisMax - axisMin);
151  }
152 
153  return res;
154  }
155 
156  T getIntersectionExtentDistance(const Box<T, N>& other) const noexcept {
157  T res = 0;
158 
159  for (std::size_t i = 0; i < N; ++i) {
160  auto axisMin = std::max(min[i], other.min[i]);
161  auto axisMax = std::min(max[i], other.max[i]);
162 
163  if (axisMin >= axisMax) {
164  return T();
165  }
166 
167  res += (axisMax - axisMin);
168  }
169 
170  return res;
171  }
172 
173  constexpr void extend(const T (&point)[N]) noexcept {
174  for (std::size_t i = 0; i < N; ++i) {
175  T axisMin = min[i];
176  T axisMax = max[i];
177  std::tie(min[i], max[i]) = std::minmax({ axisMin, axisMax, point[i] });
178  }
179  }
180 
181  constexpr void extend(Vector<T, N> point) noexcept {
182  for (std::size_t i = 0; i < N; ++i) {
183  T axisMin = min[i];
184  T axisMax = max[i];
185  std::tie(min[i], max[i]) = std::minmax({ axisMin, axisMax, point[i] });
186  }
187  }
188 
189  constexpr void extend(const Box<T, N>& other) noexcept {
190  for (std::size_t i = 0; i < N; ++i) {
191  min[i] = std::min(min[i], other.min[i]);
192  max[i] = std::max(max[i], other.max[i]);
193  }
194  }
195 
196  constexpr Box<T, N> getExtended(const Box<T, N>& other) const noexcept {
197  Box<T, N> res(*this);
198  res.extend(other);
199  return res;
200  }
201 
202  constexpr T getVolume() const noexcept {
203  T volume = 1;
204 
205  for (std::size_t i = 0; i < N; ++i) {
206  volume *= (max[i] - min[i]);
207  }
208 
209  return volume;
210  }
211 
212  constexpr T getExtentDistance() const noexcept {
213  T distance = 0;
214 
215  for (std::size_t i = 0; i < N; ++i) {
216  distance += (max[i] - min[i]);
217  }
218 
219  return distance;
220  }
221 
222  constexpr T getMinimumEdge() const noexcept {
223  T minimum = max[0] - min[0];
224 
225  for (std::size_t i = 1; i < N; ++i) {
226  minimum = std::min(minimum, max[i] - min[i]);
227  }
228 
229  return minimum;
230  }
231 
235  constexpr void normalize() noexcept {
236  for (std::size_t i = 0; i < N; ++i) {
237  if (min[i] > max[i]) {
238  std::swap(min[i], max[i]);
239  }
240  }
241  }
242  };
243 
246 
249 
252 
253 
254  enum Quadrant {
259  };
260 
261  template<typename T>
262  inline
264  Vector<T, 2> size = (box.max - box.min) / 2;
265 
266  switch (quadrant) {
267  case Quadrant::UpperLeft:
268  return Box<T,2>(box.min, box.max - size);
269  case Quadrant::UpperRight:
270  return Box<T,2>({ box.min.x + size.width, box.min.y }, { box.max.x, box.max.y - size.height });
271  case Quadrant::LowerRight:
272  return Box<T,2>(box.min + size, box.max);
273  case Quadrant::LowerLeft:
274  return Box<T,2>({ box.min.x, box.min.y + size.height }, { box.max.x - size.width, box.max.y });
275  }
276 
277  return box;
278  }
279 
280  template<typename T, std::size_t N>
281  constexpr
282  bool operator==(const Box<T, N>& lhs, const Box<T, N>& rhs) {
283  return lhs.min == rhs.min && lhs.max == rhs.max;
284  }
285 
286 // template<typename T, std::size_t N>
287 // constexpr
288 // Box<T, N> extension(const Box<T, N>& lhs, const Box<T, N>& rhs) {
289 // Box<T, N> res(lhs);
290 // res.extend(rhs);
291 // return res;
292 // }
293 //
294 // template<typename T, std::size_t N>
295 // constexpr
296 // Box<T, N> operator+(const Box<T, N>& lhs, const Box<T, N>& rhs) {
297 // return extension(lhs, rhs);
298 // }
299 //
300 // template<typename T, std::size_t N>
301 // constexpr
302 // Box<T, N>& operator+=(Box<T, N> lhs, const Box<T, N>& rhs) {
303 // lhs.extend(rhs);
304 // return lhs;
305 // }
306 
307 
308 #ifndef DOXYGEN_SHOULD_SKIP_THIS
309 }
310 #endif
311 }
312 
313 #endif // GF_BOX_H
constexpr Box< T, N > getExtended(const Box< T, N > &other) const noexcept
Definition: Box.h:196
constexpr Vector< T, N > max(Vector< T, N > lhs, Vector< T, N > rhs)
Component-wise maximum.
Definition: VectorOps.h:464
Definition: Box.h:257
constexpr bool intersects(const Box< T, N > &other) const noexcept
Definition: Box.h:118
constexpr Box(const T(&p0)[N], const T(&p1)[N]) noexcept
Definition: Box.h:67
constexpr T getMinimumEdge() const noexcept
Definition: Box.h:222
constexpr bool contains(const Box< T, N > &other) const noexcept
Definition: Box.h:108
constexpr bool operator==(const Box< T, N > &lhs, const Box< T, N > &rhs)
Definition: Box.h:282
constexpr void extend(Vector< T, N > point) noexcept
Definition: Box.h:181
constexpr Box(Vector< T, N > p0, Vector< T, N > p1) noexcept
Definition: Box.h:60
Vector< T, N > min
Definition: Box.h:49
constexpr Vector< T, N > getCenter() const noexcept
Definition: Box.h:94
constexpr bool isEmpty() const noexcept
Definition: Box.h:84
T getIntersectionVolume(const Box< T, N > &other) const noexcept
Definition: Box.h:139
Definition: Box.h:255
T width
First coordinate in the size representation.
Definition: Vector.h:512
constexpr T getExtentDistance() const noexcept
Definition: Box.h:212
constexpr void normalize() noexcept
Ensures that min coordinates are less than max coordinates.
Definition: Box.h:235
constexpr Box() noexcept
Definition: Box.h:52
T height
Second coordinate in the size representation.
Definition: Vector.h:523
constexpr Vector< T, N > getSize() const noexcept
Definition: Box.h:80
constexpr T getVolume() const noexcept
Definition: Box.h:202
The namespace for gf classes.
Definition: Action.h:35
constexpr void extend(const T(&point)[N]) noexcept
Definition: Box.h:173
T getIntersectionExtentDistance(const Box< T, N > &other) const noexcept
Definition: Box.h:156
constexpr Vector< T, N > min(Vector< T, N > lhs, Vector< T, N > rhs)
Component-wise minimum.
Definition: VectorOps.h:448
constexpr void extend(const Box< T, N > &other) noexcept
Definition: Box.h:189
Vector< T, N > max
Definition: Box.h:50
A 2D vector.
Definition: Vector.h:316
Box< T, 2 > computeBoxQuadrant(const Box< T, 2 > &box, Quadrant quadrant)
Definition: Box.h:263
Quadrant
Definition: Box.h:254
Definition: Box.h:256
constexpr bool contains(Vector< T, N > point) const noexcept
Definition: Box.h:98
A multi-dimensional box.
Definition: Box.h:48
General purpose math vector.
Definition: Vector.h:61
Box< T, N > getIntersection(const Box< T, N > &other) const noexcept
Definition: Box.h:128
Definition: Box.h:258
constexpr Box(Vector< T, N > p) noexcept
Definition: Box.h:73