rect.h 7.8 KB

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