rect.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #pragma once
  5. #include "irrTypes.h"
  6. #include "dimension2d.h"
  7. #include "position2d.h"
  8. namespace core
  9. {
  10. //! Rectangle template.
  11. /** Mostly used by 2D GUI elements and for 2D drawing methods.
  12. It has 2 positions instead of position and dimension and a fast
  13. method for collision detection with other rectangles and points.
  14. Coordinates are (0,0) for top-left corner, and increasing to the right
  15. and to the bottom.
  16. */
  17. template <class T>
  18. class rect
  19. {
  20. public:
  21. //! Default constructor creating empty rectangle at (0,0)
  22. constexpr rect() :
  23. UpperLeftCorner(0, 0), LowerRightCorner(0, 0) {}
  24. //! Constructor with two corners
  25. constexpr rect(T x, T y, T x2, T y2) :
  26. UpperLeftCorner(x, y), LowerRightCorner(x2, y2) {}
  27. //! Constructor with two corners
  28. constexpr rect(const position2d<T> &upperLeft, const position2d<T> &lowerRight) :
  29. UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {}
  30. //! Constructor with upper left corner and dimension
  31. template <class U>
  32. constexpr rect(const position2d<T> &pos, const dimension2d<U> &size) :
  33. UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height)
  34. {
  35. }
  36. //! Constructor with upper left at 0,0 and lower right using dimension
  37. template <class U>
  38. explicit constexpr rect(const dimension2d<U> &size) :
  39. UpperLeftCorner(0, 0), LowerRightCorner(size.Width, size.Height)
  40. {
  41. }
  42. //! move right by given numbers
  43. rect<T> operator+(const position2d<T> &pos) const
  44. {
  45. rect<T> ret(*this);
  46. return ret += pos;
  47. }
  48. //! move right by given numbers
  49. rect<T> &operator+=(const position2d<T> &pos)
  50. {
  51. UpperLeftCorner += pos;
  52. LowerRightCorner += pos;
  53. return *this;
  54. }
  55. //! move left by given numbers
  56. rect<T> operator-(const position2d<T> &pos) const
  57. {
  58. rect<T> ret(*this);
  59. return ret -= pos;
  60. }
  61. //! move left by given numbers
  62. rect<T> &operator-=(const position2d<T> &pos)
  63. {
  64. UpperLeftCorner -= pos;
  65. LowerRightCorner -= pos;
  66. return *this;
  67. }
  68. //! equality operator
  69. constexpr bool operator==(const rect<T> &other) const
  70. {
  71. return (UpperLeftCorner == other.UpperLeftCorner &&
  72. LowerRightCorner == other.LowerRightCorner);
  73. }
  74. //! inequality operator
  75. constexpr bool operator!=(const rect<T> &other) const
  76. {
  77. return (UpperLeftCorner != other.UpperLeftCorner ||
  78. LowerRightCorner != other.LowerRightCorner);
  79. }
  80. //! compares size of rectangles
  81. bool operator<(const rect<T> &other) const
  82. {
  83. return getArea() < other.getArea();
  84. }
  85. //! Returns size of rectangle
  86. T getArea() const
  87. {
  88. return getWidth() * getHeight();
  89. }
  90. //! Returns if a 2d point is within this rectangle.
  91. /** \param pos Position to test if it lies within this rectangle.
  92. \return True if the position is within the rectangle, false if not. */
  93. bool isPointInside(const position2d<T> &pos) const
  94. {
  95. return (UpperLeftCorner.X <= pos.X &&
  96. UpperLeftCorner.Y <= pos.Y &&
  97. LowerRightCorner.X >= pos.X &&
  98. LowerRightCorner.Y >= pos.Y);
  99. }
  100. //! Check if the rectangle collides with another rectangle.
  101. /** \param other Rectangle to test collision with
  102. \return True if the rectangles collide. */
  103. bool isRectCollided(const rect<T> &other) const
  104. {
  105. return (LowerRightCorner.Y > other.UpperLeftCorner.Y &&
  106. UpperLeftCorner.Y < other.LowerRightCorner.Y &&
  107. LowerRightCorner.X > other.UpperLeftCorner.X &&
  108. UpperLeftCorner.X < other.LowerRightCorner.X);
  109. }
  110. //! Clips this rectangle with another one.
  111. /** \param other Rectangle to clip with */
  112. void clipAgainst(const rect<T> &other)
  113. {
  114. if (other.LowerRightCorner.X < LowerRightCorner.X)
  115. LowerRightCorner.X = other.LowerRightCorner.X;
  116. if (other.LowerRightCorner.Y < LowerRightCorner.Y)
  117. LowerRightCorner.Y = other.LowerRightCorner.Y;
  118. if (other.UpperLeftCorner.X > LowerRightCorner.X)
  119. LowerRightCorner.X = other.UpperLeftCorner.X;
  120. if (other.UpperLeftCorner.Y > LowerRightCorner.Y)
  121. LowerRightCorner.Y = other.UpperLeftCorner.Y;
  122. if (other.LowerRightCorner.X < UpperLeftCorner.X)
  123. UpperLeftCorner.X = other.LowerRightCorner.X;
  124. if (other.LowerRightCorner.Y < UpperLeftCorner.Y)
  125. UpperLeftCorner.Y = other.LowerRightCorner.Y;
  126. if (other.UpperLeftCorner.X > UpperLeftCorner.X)
  127. UpperLeftCorner.X = other.UpperLeftCorner.X;
  128. if (other.UpperLeftCorner.Y > UpperLeftCorner.Y)
  129. UpperLeftCorner.Y = other.UpperLeftCorner.Y;
  130. }
  131. //! Moves this rectangle to fit inside another one.
  132. /** \return True on success, false if not possible */
  133. bool constrainTo(const rect<T> &other)
  134. {
  135. if (other.getWidth() < getWidth() || other.getHeight() < getHeight())
  136. return false;
  137. T diff = other.LowerRightCorner.X - LowerRightCorner.X;
  138. if (diff < 0) {
  139. LowerRightCorner.X += diff;
  140. UpperLeftCorner.X += diff;
  141. }
  142. diff = other.LowerRightCorner.Y - LowerRightCorner.Y;
  143. if (diff < 0) {
  144. LowerRightCorner.Y += diff;
  145. UpperLeftCorner.Y += diff;
  146. }
  147. diff = UpperLeftCorner.X - other.UpperLeftCorner.X;
  148. if (diff < 0) {
  149. UpperLeftCorner.X -= diff;
  150. LowerRightCorner.X -= diff;
  151. }
  152. diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y;
  153. if (diff < 0) {
  154. UpperLeftCorner.Y -= diff;
  155. LowerRightCorner.Y -= diff;
  156. }
  157. return true;
  158. }
  159. //! Get width of rectangle.
  160. T getWidth() const
  161. {
  162. return LowerRightCorner.X - UpperLeftCorner.X;
  163. }
  164. //! Get height of rectangle.
  165. T getHeight() const
  166. {
  167. return LowerRightCorner.Y - UpperLeftCorner.Y;
  168. }
  169. //! If the lower right corner of the rect is smaller then the upper left, the points are swapped.
  170. void repair()
  171. {
  172. if (LowerRightCorner.X < UpperLeftCorner.X) {
  173. T t = LowerRightCorner.X;
  174. LowerRightCorner.X = UpperLeftCorner.X;
  175. UpperLeftCorner.X = t;
  176. }
  177. if (LowerRightCorner.Y < UpperLeftCorner.Y) {
  178. T t = LowerRightCorner.Y;
  179. LowerRightCorner.Y = UpperLeftCorner.Y;
  180. UpperLeftCorner.Y = t;
  181. }
  182. }
  183. //! Returns if the rect is valid to draw.
  184. /** It would be invalid if the UpperLeftCorner is lower or more
  185. right than the LowerRightCorner. */
  186. bool isValid() const
  187. {
  188. return ((LowerRightCorner.X >= UpperLeftCorner.X) &&
  189. (LowerRightCorner.Y >= UpperLeftCorner.Y));
  190. }
  191. //! Get the center of the rectangle
  192. position2d<T> getCenter() const
  193. {
  194. return position2d<T>(
  195. (UpperLeftCorner.X + LowerRightCorner.X) / 2,
  196. (UpperLeftCorner.Y + LowerRightCorner.Y) / 2);
  197. }
  198. //! Get the dimensions of the rectangle
  199. dimension2d<T> getSize() const
  200. {
  201. return dimension2d<T>(getWidth(), getHeight());
  202. }
  203. //! Adds a point to the rectangle
  204. /** Causes the rectangle to grow bigger if point is outside of
  205. the box
  206. \param p Point to add to the box. */
  207. void addInternalPoint(const position2d<T> &p)
  208. {
  209. addInternalPoint(p.X, p.Y);
  210. }
  211. //! Adds a point to the bounding rectangle
  212. /** Causes the rectangle to grow bigger if point is outside of
  213. the box
  214. \param x X-Coordinate of the point to add to this box.
  215. \param y Y-Coordinate of the point to add to this box. */
  216. void addInternalPoint(T x, T y)
  217. {
  218. if (x > LowerRightCorner.X)
  219. LowerRightCorner.X = x;
  220. if (y > LowerRightCorner.Y)
  221. LowerRightCorner.Y = y;
  222. if (x < UpperLeftCorner.X)
  223. UpperLeftCorner.X = x;
  224. if (y < UpperLeftCorner.Y)
  225. UpperLeftCorner.Y = y;
  226. }
  227. //! Upper left corner
  228. position2d<T> UpperLeftCorner;
  229. //! Lower right corner
  230. position2d<T> LowerRightCorner;
  231. };
  232. //! Rectangle with float values
  233. typedef rect<f32> rectf;
  234. //! Rectangle with int values
  235. typedef rect<s32> recti;
  236. } // end namespace core