Gamedev Framework (gf)  0.14.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 "Quarter.h"
34 #include "Vector.h"
35 #include "VectorOps.h"
36 
37 namespace gf {
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
39 inline namespace v1 {
40 #endif
41 
51  template<typename T, std::size_t N>
52  struct Box {
55 
59  constexpr Box() noexcept
60  {
61  for (std::size_t i = 0; i < N; ++i) {
62  min[i] = std::numeric_limits<T>::max();
63  max[i] = std::numeric_limits<T>::lowest();
64  }
65  }
66 
73  constexpr Box(Vector<T, N> p0, Vector<T, N> p1) noexcept
74  : min(gf::Zero)
75  , max(gf::Zero)
76  {
77  for (std::size_t i = 0; i < N; ++i) {
78  if (p0[i] < p1[i]) {
79  min[i] = p0[i];
80  max[i] = p1[i];
81  } else {
82  min[i] = p1[i];
83  max[i] = p0[i];
84  }
85  }
86  }
87 
94  constexpr Box(const T (&p0)[N], const T (&p1)[N]) noexcept
95  : min(gf::Zero)
96  , max(gf::Zero)
97  {
98  for (std::size_t i = 0; i < N; ++i) {
99  if (p0[i] < p1[i]) {
100  min[i] = p0[i];
101  max[i] = p1[i];
102  } else {
103  min[i] = p1[i];
104  max[i] = p0[i];
105  }
106  }
107  }
108 
114  constexpr explicit Box(Vector<T, N> p) noexcept
115  : min(p)
116  , max(p)
117  {
118 
119  }
120 
128  constexpr Vector<T, N> getPosition() const noexcept {
129  return min;
130  }
131 
137  constexpr Vector<T, N> getSize() const noexcept {
138  return max - min;
139  }
140 
146  constexpr bool isEmpty() const noexcept {
147  for (std::size_t i = 0; i < N; ++i) {
148  if (min[i] >= max[i]) {
149  return true;
150  }
151  }
152 
153  return false;
154  }
155 
161  constexpr Vector<T, N> getCenter() const noexcept {
162  return min + (max - min) / 2;
163  }
164 
171  constexpr bool contains(Vector<T, N> point) const noexcept {
172  for (std::size_t i = 0; i < N; ++i) {
173  if (!(min[i] <= point[i] && point[i] < max[i])) {
174  return false;
175  }
176  }
177 
178  return true;
179  }
180 
187  constexpr bool contains(const Box<T, N>& other) const noexcept {
188  for (std::size_t i = 0; i < N; ++i) {
189  if (!(min[i] <= other.min[i] && other.max[i] <= max[i])) {
190  return false;
191  }
192  }
193 
194  return true;
195  }
196 
203  constexpr bool intersects(const Box<T, N>& other) const noexcept {
204  for (std::size_t i = 0; i < N; ++i) {
205  if (!(min[i] < other.max[i] && other.min[i] < max[i])) {
206  return false;
207  }
208  }
209 
210  return true;
211  }
212 
220  constexpr bool intersects(const Box<T, N>& other, Box<T, N>& result) const noexcept {
221  if (!intersects(other)) {
222  return false;
223  }
224 
225  result = getIntersection(other);
226  return true;
227  }
228 
235  constexpr Box<T, N> getIntersection(const Box<T, N>& other) const noexcept {
236  Box<T, N> res;
237 
238  for (std::size_t i = 0; i < N; ++i) {
239  res.min[i] = std::max(min[i], other.min[i]);
240  res.max[i] = std::min(max[i], other.max[i]);
241  }
242 
243  return res;
244  }
245 
252  constexpr T getIntersectionVolume(const Box<T, N>& other) const noexcept {
253  T res = 1;
254 
255  for (std::size_t i = 0; i < N; ++i) {
256  auto axisMin = std::max(min[i], other.min[i]);
257  auto axisMax = std::min(max[i], other.max[i]);
258 
259  if (axisMin >= axisMax) {
260  return T();
261  }
262 
263  res *= (axisMax - axisMin);
264  }
265 
266  return res;
267  }
268 
275  constexpr T getIntersectionExtentLength(const Box<T, N>& other) const noexcept {
276  T res = 0;
277 
278  for (std::size_t i = 0; i < N; ++i) {
279  auto axisMin = std::max(min[i], other.min[i]);
280  auto axisMax = std::min(max[i], other.max[i]);
281 
282  if (axisMin >= axisMax) {
283  return T();
284  }
285 
286  res += (axisMax - axisMin);
287  }
288 
289  return res;
290  }
291 
297  constexpr void extend(const T (&point)[N]) noexcept {
298  for (std::size_t i = 0; i < N; ++i) {
299  T axisMin = min[i];
300  T axisMax = max[i];
301  std::tie(min[i], max[i]) = std::minmax({ axisMin, axisMax, point[i] });
302  }
303  }
304 
310  constexpr void extend(Vector<T, N> point) noexcept {
311  for (std::size_t i = 0; i < N; ++i) {
312  T axisMin = min[i];
313  T axisMax = max[i];
314  std::tie(min[i], max[i]) = std::minmax({ axisMin, axisMax, point[i] });
315  }
316  }
317 
323  constexpr void extend(const Box<T, N>& other) noexcept {
324  for (std::size_t i = 0; i < N; ++i) {
325  min[i] = std::min(min[i], other.min[i]);
326  max[i] = std::max(max[i], other.max[i]);
327  }
328  }
329 
335  constexpr Box<T, N> getExtended(const Box<T, N>& other) const noexcept {
336  Box<T, N> res(*this);
337  res.extend(other);
338  return res;
339  }
340 
346  constexpr T getVolume() const noexcept {
347  T volume = 1;
348 
349  for (std::size_t i = 0; i < N; ++i) {
350  volume *= (max[i] - min[i]);
351  }
352 
353  return volume;
354  }
355 
361  constexpr T getExtentLength() const noexcept {
362  T distance = 0;
363 
364  for (std::size_t i = 0; i < N; ++i) {
365  distance += (max[i] - min[i]);
366  }
367 
368  return distance;
369  }
370 
376  constexpr T getMinimumEdge() const noexcept {
377  T minimum = max[0] - min[0];
378 
379  for (std::size_t i = 1; i < N; ++i) {
380  minimum = std::min(minimum, max[i] - min[i]);
381  }
382 
383  return minimum;
384  }
385 
393  constexpr Box<T, 2> grow(T value) const noexcept {
394  return Box<T, 2>(min - value, max + value);
395  }
396 
404  constexpr Box<T, 2> shrink(T value) const noexcept {
405  return Box<T, 2>(min + value, max - value);
406  }
407 
411  constexpr void normalize() noexcept {
412  for (std::size_t i = 0; i < N; ++i) {
413  if (min[i] > max[i]) {
414  std::swap(min[i], max[i]);
415  }
416  }
417  }
418  };
419 
425 
431 
437 
443 
449 
455 
456 
464  template<typename T>
465  constexpr
467  Vector<T, 2> size = (box.max - box.min) / 2;
468 
469  switch (quarter) {
470  case Quarter::UpperLeft:
471  return Box<T,2>(box.min, box.max - size);
472  case Quarter::UpperRight:
473  return Box<T,2>({ box.min.x + size.width, box.min.y }, { box.max.x, box.max.y - size.height });
474  case Quarter::LowerRight:
475  return Box<T,2>(box.min + size, box.max);
476  case Quarter::LowerLeft:
477  return Box<T,2>({ box.min.x, box.min.y + size.height }, { box.max.x - size.width, box.max.y });
478  }
479 
480  return box;
481  }
482 
487  template<typename T, std::size_t N>
488  constexpr
489  bool operator==(const Box<T, N>& lhs, const Box<T, N>& rhs) {
490  return lhs.min == rhs.min && lhs.max == rhs.max;
491  }
492 
493 
494 #ifndef DOXYGEN_SHOULD_SKIP_THIS
495 }
496 #endif
497 }
498 
499 #endif // GF_BOX_H
constexpr Box< T, N > getExtended(const Box< T, N > &other) const noexcept
Get the box extended by another box.
Definition: Box.h:335
constexpr Vector< T, N > max(Vector< T, N > lhs, Vector< T, N > rhs)
Component-wise maximum.
Definition: VectorOps.h:464
constexpr bool intersects(const Box< T, N > &other) const noexcept
Check if two boxes interset.
Definition: Box.h:203
Upper-right quarter.
Definition: Quarter.h:35
constexpr Box(const T(&p0)[N], const T(&p1)[N]) noexcept
Constructor with two points (as arrays)
Definition: Box.h:94
constexpr bool intersects(const Box< T, N > &other, Box< T, N > &result) const noexcept
Check if two boxes interset and get the intersetion box.
Definition: Box.h:220
constexpr T getMinimumEdge() const noexcept
Get the minimum edge of the box.
Definition: Box.h:376
constexpr bool contains(const Box< T, N > &other) const noexcept
Check if a box is totally inside the box.
Definition: Box.h:187
constexpr Box< T, N > getIntersection(const Box< T, N > &other) const noexcept
Compute the intersection of two boxes.
Definition: Box.h:235
constexpr void extend(Vector< T, N > point) noexcept
Extend the box with a point.
Definition: Box.h:310
constexpr Box(Vector< T, N > p0, Vector< T, N > p1) noexcept
Constructor with two points.
Definition: Box.h:73
Vector< T, N > min
The minimum point of the box.
Definition: Box.h:53
constexpr Box< T, 2 > computeBoxQuarter(const Box< T, 2 > &box, Quarter quarter)
Divide a box in quarters.
Definition: Box.h:466
constexpr Vector< T, N > getCenter() const noexcept
Get the center of the box.
Definition: Box.h:161
Lower-right quarter.
Definition: Quarter.h:36
constexpr bool isEmpty() const noexcept
Check if the box is empty.
Definition: Box.h:146
Upper-left quarter.
Definition: Quarter.h:34
T width
First coordinate in the size representation.
Definition: Vector.h:510
constexpr void normalize() noexcept
Ensures that min coordinates are less than max coordinates.
Definition: Box.h:411
constexpr Box< T, 2 > grow(T value) const noexcept
Grow the box.
Definition: Box.h:393
constexpr Box() noexcept
Default constructor.
Definition: Box.h:59
T height
Second coordinate in the size representation.
Definition: Vector.h:521
constexpr Vector< T, N > getSize() const noexcept
Get the size of the box.
Definition: Box.h:137
constexpr T getVolume() const noexcept
Get the volume of the box.
Definition: Box.h:346
The namespace for gf classes.
Definition: Action.h:35
constexpr void extend(const T(&point)[N]) noexcept
Extend the box with a point (as array)
Definition: Box.h:297
constexpr Vector< T, N > min(Vector< T, N > lhs, Vector< T, N > rhs)
Component-wise minimum.
Definition: VectorOps.h:448
Lower-left quarter.
Definition: Quarter.h:37
constexpr bool operator==(const Box< T, N > &lhs, const Box< T, N > &rhs)
Equality operator.
Definition: Box.h:489
constexpr void extend(const Box< T, N > &other) noexcept
Extend the box with a box.
Definition: Box.h:323
Vector< T, N > max
The maximum point of the box.
Definition: Box.h:54
Quarter
A quarter in a square.
Definition: Quarter.h:33
A 2D vector.
Definition: Vector.h:316
constexpr Vector< T, N > getPosition() const noexcept
Get the position of the box.
Definition: Box.h:128
constexpr T getExtentLength() const noexcept
Get the extent length of the box.
Definition: Box.h:361
constexpr T getIntersectionVolume(const Box< T, N > &other) const noexcept
Get the volume of the intersection.
Definition: Box.h:252
constexpr bool contains(Vector< T, N > point) const noexcept
Check if a point is inside the box.
Definition: Box.h:171
A multi-dimensional box.
Definition: Box.h:52
General purpose math vector.
Definition: Vector.h:61
constexpr T getIntersectionExtentLength(const Box< T, N > &other) const noexcept
Get the extent length of the intersection.
Definition: Box.h:275
constexpr Box< T, 2 > shrink(T value) const noexcept
Shrink the box.
Definition: Box.h:404
constexpr Box(Vector< T, N > p) noexcept
Constructor with one point.
Definition: Box.h:114