Gamedev Framework (gf)  0.20.0
A C++17 framework for 2D games
Rect.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2021 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_RECT_H
25 #define GF_RECT_H
26 
27 #include <cstddef>
28 #include <algorithm>
29 #include <limits>
30 #include <tuple>
31 
32 #include "Anchor.h"
33 #include "CoreApi.h"
34 #include "Quarter.h"
35 #include "Vector.h"
36 #include "VectorOps.h"
37 
38 namespace gf {
39 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 inline namespace v1 {
41 #endif
42 
86  template<typename T>
87  struct Rect {
93  constexpr Rect() noexcept
94  : min(gf::Zero)
95  , max(gf::Zero)
96  {
97  }
98 
106  static constexpr Rect<T> fromMinMax(Vector<T, 2> min, Vector<T, 2> max) noexcept {
107  return Rect<T>(min, max);
108  }
109 
117  static constexpr Rect<T> fromPositionSize(Vector<T, 2> position, Vector<T, 2> size) noexcept {
118  return Rect<T>(position, position + size);
119  }
120 
129  static constexpr Rect<T> fromSize(Vector<T, 2> size) noexcept {
130  return Rect<T>({ T(0), T(0) }, size);
131  }
132 
140  static constexpr Rect<T> fromCenterSize(Vector<T, 2> center, Vector<T, 2> size) noexcept {
141  return Rect<T>(center - size / T(2), center + size / T(2));
142  }
143 
149  static constexpr Rect<T> empty() noexcept {
150  return Rect<T>(Vector<T, 2>(std::numeric_limits<T>::max()), Vector<T, 2>(std::numeric_limits<T>::lowest()));
151  }
152 
160  constexpr Vector<T, 2> getPosition() const noexcept {
161  return min;
162  }
163 
169  constexpr Vector<T, 2> getSize() const noexcept {
170  return max - min;
171  }
172 
178  constexpr bool isEmpty() const noexcept {
179  return min.x >= max.x || min.y >= max.y;
180  }
181 
187  constexpr Vector<T, 2> getCenter() const noexcept {
188  return min + (max - min) / 2;
189  }
190 
197  constexpr bool contains(Vector<T, 2> point) const noexcept {
198  return min.x <= point.x && point.x < max.x && min.y <= point.y && point.y < max.y;
199  }
200 
207  constexpr bool contains(const Rect& other) const noexcept {
208  return min.x <= other.min.x && other.max.x <= max.x && min.y <= other.min.y && other.max.y <= max.y;
209  }
210 
217  constexpr bool intersects(const Rect& other) const noexcept {
218  return min.x < other.max.x && other.min.x < max.x && min.y < other.max.y && other.min.y < max.y;
219  }
220 
228  constexpr bool intersects(const Rect& other, Rect& result) const noexcept {
229  if (!intersects(other)) {
230  return false;
231  }
232 
233  result = getIntersection(other);
234  return true;
235  }
236 
243  constexpr Rect getIntersection(const Rect& other) const noexcept {
244  Rect res;
245 
246  res.min.x = std::max(min.x, other.min.x);
247  res.min.y = std::max(min.y, other.min.y);
248  res.max.x = std::min(max.x, other.max.x);
249  res.max.y = std::min(max.y, other.max.y);
250 
251  return res;
252  }
253 
260  constexpr T getIntersectionVolume(const Rect& other) const noexcept {
261  auto xMin = std::max(min.x, other.min.x);
262  auto xMax = std::min(max.x, other.max.x);
263 
264  if (xMin >= xMax) {
265  return T(0);
266  }
267 
268  auto yMin = std::max(min.y, other.min.y);
269  auto yMax = std::min(max.y, other.max.y);
270 
271  if (yMin >= yMax) {
272  return T(0);
273  }
274 
275  return (xMax - xMin) * (yMax - yMin);
276  }
277 
284  constexpr T getIntersectionExtentLength(const Rect& other) const noexcept {
285  auto xMin = std::max(min.x, other.min.x);
286  auto xMax = std::min(max.x, other.max.x);
287 
288  if (xMin >= xMax) {
289  return T(0);
290  }
291 
292  auto yMin = std::max(min.y, other.min.y);
293  auto yMax = std::min(max.y, other.max.y);
294 
295  if (yMin >= yMax) {
296  return T(0);
297  }
298 
299  return (xMax - xMin) + (yMax - yMin);
300  }
301 
307  constexpr void extend(const T (&point)[2]) noexcept {
308  min.x = std::min(min.x, point[0]);
309  min.y = std::min(min.y, point[1]);
310  max.x = std::max(max.x, point[0]);
311  max.y = std::max(max.y, point[1]);
312  }
313 
319  constexpr void extend(Vector<T, 2> point) noexcept {
320  min.x = std::min(min.x, point.x);
321  min.y = std::min(min.y, point.y);
322  max.x = std::max(max.x, point.x);
323  max.y = std::max(max.y, point.y);
324  }
325 
331  constexpr void extend(const Rect& other) noexcept {
332  min.x = std::min(min.x, other.min.x);
333  min.y = std::min(min.y, other.min.y);
334  max.x = std::max(max.x, other.max.x);
335  max.y = std::max(max.y, other.max.y);
336  }
337 
343  constexpr Rect getExtended(const Rect& other) const noexcept {
344  Rect res(*this);
345  res.extend(other);
346  return res;
347  }
348 
354  constexpr T getVolume() const noexcept {
355  return (max.x - min.x) * (max.y - min.y);
356  }
357 
363  constexpr T getExtentLength() const noexcept {
364  return (max.x - min.x) + (max.y - min.y);
365  }
366 
372  constexpr T getMinimumEdge() const noexcept {
373  return std::min(max.x - min.x, max.y - min.y);
374  }
375 
383  constexpr Rect grow(T value) const noexcept {
384  return Rect(min - value, max + value);
385  }
386 
394  constexpr Rect shrink(T value) const noexcept {
395  return Rect(min + value, max - value);
396  }
397 
401  constexpr void normalize() noexcept {
402  if (min.x > max.x) { std::swap(min.x, max.x); }
403  if (min.y > max.y) { std::swap(min.y, max.y); }
404  }
405 
412  constexpr Vector<T, 2> getPositionFromAnchor(Anchor anchor) const noexcept {
413  switch (anchor) {
414  case Anchor::TopLeft:
415  return this->min;
416  case Anchor::TopCenter:
417  return { (this->min.x + this->max.x) / T(2), this->min.y };
418  case Anchor::TopRight:
419  return { this->max.x, this->min.y };
420  case Anchor::CenterLeft:
421  return { this->min.x, (this->min.y + this->max.y) / T(2) };
422  case Anchor::Center:
423  return this->getCenter();
424  case Anchor::CenterRight:
425  return { this->max.x, (this->min.y + this->max.y) / T(2) };
426  case Anchor::BottomLeft:
427  return { this->min.x, this->max.y };
429  return { (this->min.x + this->max.x) / T(2), this->max.y };
430  case Anchor::BottomRight:
431  return this->max;
432  }
433 
434  return this->min;
435  }
436 
442  constexpr Vector<T, 2> getTopLeft() const noexcept {
443  return getPositionFromAnchor(Anchor::TopLeft);
444  }
445 
451  constexpr Vector<T, 2> getTopRight() const noexcept {
452  return getPositionFromAnchor(Anchor::TopRight);
453  }
454 
460  constexpr Vector<T, 2> getBottomLeft() const noexcept {
461  return getPositionFromAnchor(Anchor::BottomLeft);
462  }
463 
469  constexpr Vector<T, 2> getBottomRight() const noexcept {
470  return getPositionFromAnchor(Anchor::BottomRight);
471  }
472 
478  constexpr T getWidth() const noexcept {
479  return this->max.x - this->min.x;
480  }
481 
487  constexpr T getHeight() const noexcept {
488  return this->max.y - this->min.y;
489  }
490 
493 
494  private:
495  constexpr Rect(Vector<T, 2> min, Vector<T, 2> max) noexcept
496  : min(min)
497  , max(max)
498  {
499  }
500  };
501 
509 
517 
524  using RectI = Rect<int>;
525 
533 
541 
542 // MSVC does not like extern template
543 #ifndef _MSC_VER
544  extern template struct GF_CORE_API Rect<float>;
545  extern template struct GF_CORE_API Rect<double>;
546  extern template struct GF_CORE_API Rect<int>;
547  extern template struct GF_CORE_API Rect<unsigned>;
548 #endif
549 
558  template<typename T>
559  inline
560  bool operator==(const Rect<T>& lhs, const Rect<T>& rhs) {
561  return lhs.min == rhs.min && lhs.max == rhs.max;
562  }
563 
572  template<typename T>
573  inline
574  bool operator!=(const Rect<T>& lhs, const Rect<T>& rhs) {
575  return !(lhs == rhs);
576  }
577 
585  template<typename T>
586  constexpr
587  Rect<T> computeBoxQuarter(const Rect<T>& other, Quarter quarter) {
588  Vector<T, 2> size = (other.max - other.min) / 2;
589 
590  switch (quarter) {
591  case Quarter::UpperLeft:
592  return Rect<T>::fromMinMax(other.min, other.max - size);
593  case Quarter::UpperRight:
594  return Rect<T>::fromMinMax({ other.min.x + size.width, other.min.y }, { other.max.x, other.max.y - size.height });
595  case Quarter::LowerRight:
596  return Rect<T>::fromMinMax(other.min + size, other.max);
597  case Quarter::LowerLeft:
598  return Rect<T>::fromMinMax({ other.min.x, other.min.y + size.height }, { other.max.x - size.width, other.max.y });
599  }
600 
601  return other;
602  }
603 
612  template<typename Archive, typename T>
613  Archive& operator|(Archive& ar, Rect<T>& rect) {
614  return ar | rect.min.x | rect.min.y | rect.max.x | rect.max.y;
615  }
616 
617 
618 #ifndef DOXYGEN_SHOULD_SKIP_THIS
619 }
620 #endif
621 }
622 
623 #endif // GF_RECT_H
T x
First coordinate in the (x,y) representation.
Definition: Vector.h:514
constexpr bool contains(Vector< T, 2 > point) const noexcept
Check if a point is inside the rectangle.
Definition: Rect.h:197
constexpr T getIntersectionExtentLength(const Rect &other) const noexcept
Get the extent length of the intersection.
Definition: Rect.h:284
constexpr Rect< T > computeBoxQuarter(const Rect< T > &other, Quarter quarter)
Divide a rectangle in quarters.
Definition: Rect.h:587
constexpr Vector< T, 2 > getBottomLeft() const noexcept
Get the bottom left corner.
Definition: Rect.h:460
Vector< T, 2 > max
The maximum point of the rectangle.
Definition: Rect.h:492
bool operator!=(const Rect< T > &lhs, const Rect< T > &rhs)
Inequality operator.
Definition: Rect.h:574
constexpr bool isEmpty() const noexcept
Check if the rectangle is empty.
Definition: Rect.h:178
static constexpr Rect< T > fromSize(Vector< T, 2 > size) noexcept
Create a rectangle from a size.
Definition: Rect.h:129
constexpr T getExtentLength() const noexcept
Get the extent length of the rectangle.
Definition: Rect.h:363
constexpr Vector< T, 2 > getPositionFromAnchor(Anchor anchor) const noexcept
Get a position from the rectangle and an anchor.
Definition: Rect.h:412
Vector< T, 2 > min
The minimum point of the rectangle.
Definition: Rect.h:491
constexpr bool intersects(const Rect &other) const noexcept
Check if two rectangles interset.
Definition: Rect.h:217
constexpr Rect shrink(T value) const noexcept
Shrink the rectangle.
Definition: Rect.h:394
constexpr Rect getExtended(const Rect &other) const noexcept
Get the rectangle extended by another rectangle.
Definition: Rect.h:343
Upper-right quarter.
Definition: Quarter.h:35
Archive & operator|(Archive &ar, Rect< T > &rect)
Serialize a rectangle.
Definition: Rect.h:613
Lower-right quarter.
Definition: Quarter.h:36
static constexpr Rect< T > fromMinMax(Vector< T, 2 > min, Vector< T, 2 > max) noexcept
Create a rectangle from a min point and a max point.
Definition: Rect.h:106
T y
Second coordinate in the (x,y) representation.
Definition: Vector.h:525
constexpr Vector< T, 2 > getPosition() const noexcept
Get the position of the rectangle.
Definition: Rect.h:160
T width
First coordinate in the size representation.
Definition: Vector.h:517
constexpr void extend(const T(&point)[2]) noexcept
Extend the rectangle with a point (as array)
Definition: Rect.h:307
T height
Second coordinate in the size representation.
Definition: Vector.h:528
constexpr Vector< T, 2 > getTopRight() const noexcept
Get the top right corner.
Definition: Rect.h:451
Utility class for manipulating 2D axis aligned rectangles.
Definition: Rect.h:87
The namespace for gf classes.
Definition: Action.h:35
constexpr Vector< T, 2 > getCenter() const noexcept
Get the center of the rectangle.
Definition: Rect.h:187
static constexpr Rect< T > fromPositionSize(Vector< T, 2 > position, Vector< T, 2 > size) noexcept
Create a rectangle from a position (top-left) and a size.
Definition: Rect.h:117
Quarter
A quarter in a square.
Definition: Quarter.h:33
static constexpr Rect< T > empty() noexcept
Create an empty rectangle.
Definition: Rect.h:149
constexpr void extend(Vector< T, 2 > point) noexcept
Extend the rectangle with a point.
Definition: Rect.h:319
constexpr T getMinimumEdge() const noexcept
Get the minimum edge of the rectangle.
Definition: Rect.h:372
constexpr void extend(const Rect &other) noexcept
Extend the rectangle with a rectangle.
Definition: Rect.h:331
constexpr bool intersects(const Rect &other, Rect &result) const noexcept
Check if two rectangles interset and get the intersetion rectangle.
Definition: Rect.h:228
Upper-left quarter.
Definition: Quarter.h:34
constexpr void normalize() noexcept
Ensures that min coordinates are less than max coordinates.
Definition: Rect.h:401
A 2D vector.
Definition: Vector.h:316
constexpr T getWidth() const noexcept
Get the width of the rectangle.
Definition: Rect.h:478
constexpr T getVolume() const noexcept
Get the volume of the rectangle.
Definition: Rect.h:354
constexpr Rect() noexcept
Default constructor.
Definition: Rect.h:93
constexpr Vector< T, 2 > getTopLeft() const noexcept
Get the top left corner.
Definition: Rect.h:442
static constexpr Rect< T > fromCenterSize(Vector< T, 2 > center, Vector< T, 2 > size) noexcept
Create a rectangle from a center and a size.
Definition: Rect.h:140
constexpr Rect getIntersection(const Rect &other) const noexcept
Compute the intersection of two rectangles.
Definition: Rect.h:243
constexpr Vector< T, 2 > getBottomRight() const noexcept
Get the bottom right corner.
Definition: Rect.h:469
Anchor
An anchor of a box.
Definition: Anchor.h:38
constexpr Rect grow(T value) const noexcept
Grow the rectangle.
Definition: Rect.h:383
constexpr T getIntersectionVolume(const Rect &other) const noexcept
Get the volume of the intersection.
Definition: Rect.h:260
constexpr Vector< T, 2 > getSize() const noexcept
Get the size of the rectangle.
Definition: Rect.h:169
bool operator==(const Rect< T > &lhs, const Rect< T > &rhs)
Equality operator.
Definition: Rect.h:560
constexpr T getHeight() const noexcept
Get the height of the rectangle.
Definition: Rect.h:487
constexpr bool contains(const Rect &other) const noexcept
Check if a rectangle is totally inside the rectangle.
Definition: Rect.h:207
Lower-left quarter.
Definition: Quarter.h:37