rect.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 > UpperLeftCorner.X)
  117. UpperLeftCorner.X = other.UpperLeftCorner.X;
  118. if (other.UpperLeftCorner.Y > UpperLeftCorner.Y)
  119. UpperLeftCorner.Y = other.UpperLeftCorner.Y;
  120. // correct possible invalid rect resulting from clipping
  121. if (UpperLeftCorner.Y > LowerRightCorner.Y)
  122. UpperLeftCorner.Y = LowerRightCorner.Y;
  123. if (UpperLeftCorner.X > LowerRightCorner.X)
  124. UpperLeftCorner.X = LowerRightCorner.X;
  125. }
  126. //! Moves this rectangle to fit inside another one.
  127. /** \return True on success, false if not possible */
  128. bool constrainTo(const rect<T>& other)
  129. {
  130. if (other.getWidth() < getWidth() || other.getHeight() < getHeight())
  131. return false;
  132. T diff = other.LowerRightCorner.X - LowerRightCorner.X;
  133. if (diff < 0)
  134. {
  135. LowerRightCorner.X += diff;
  136. UpperLeftCorner.X += diff;
  137. }
  138. diff = other.LowerRightCorner.Y - LowerRightCorner.Y;
  139. if (diff < 0)
  140. {
  141. LowerRightCorner.Y += diff;
  142. UpperLeftCorner.Y += diff;
  143. }
  144. diff = UpperLeftCorner.X - other.UpperLeftCorner.X;
  145. if (diff < 0)
  146. {
  147. UpperLeftCorner.X -= diff;
  148. LowerRightCorner.X -= diff;
  149. }
  150. diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y;
  151. if (diff < 0)
  152. {
  153. UpperLeftCorner.Y -= diff;
  154. LowerRightCorner.Y -= diff;
  155. }
  156. return true;
  157. }
  158. //! Get width of rectangle.
  159. T getWidth() const
  160. {
  161. return LowerRightCorner.X - UpperLeftCorner.X;
  162. }
  163. //! Get height of rectangle.
  164. T getHeight() const
  165. {
  166. return LowerRightCorner.Y - UpperLeftCorner.Y;
  167. }
  168. //! If the lower right corner of the rect is smaller then the upper left, the points are swapped.
  169. void repair()
  170. {
  171. if (LowerRightCorner.X < UpperLeftCorner.X)
  172. {
  173. T t = LowerRightCorner.X;
  174. LowerRightCorner.X = UpperLeftCorner.X;
  175. UpperLeftCorner.X = t;
  176. }
  177. if (LowerRightCorner.Y < UpperLeftCorner.Y)
  178. {
  179. T t = LowerRightCorner.Y;
  180. LowerRightCorner.Y = UpperLeftCorner.Y;
  181. UpperLeftCorner.Y = t;
  182. }
  183. }
  184. //! Returns if the rect is valid to draw.
  185. /** It would be invalid if the UpperLeftCorner is lower or more
  186. right than the LowerRightCorner. */
  187. bool isValid() const
  188. {
  189. return ((LowerRightCorner.X >= UpperLeftCorner.X) &&
  190. (LowerRightCorner.Y >= UpperLeftCorner.Y));
  191. }
  192. //! Get the center of the rectangle
  193. position2d<T> getCenter() const
  194. {
  195. return position2d<T>(
  196. (UpperLeftCorner.X + LowerRightCorner.X) / 2,
  197. (UpperLeftCorner.Y + LowerRightCorner.Y) / 2);
  198. }
  199. //! Get the dimensions of the rectangle
  200. dimension2d<T> getSize() const
  201. {
  202. return dimension2d<T>(getWidth(), getHeight());
  203. }
  204. //! Adds a point to the rectangle
  205. /** Causes the rectangle to grow bigger if point is outside of
  206. the box
  207. \param p Point to add to the box. */
  208. void addInternalPoint(const position2d<T>& p)
  209. {
  210. addInternalPoint(p.X, p.Y);
  211. }
  212. //! Adds a point to the bounding rectangle
  213. /** Causes the rectangle to grow bigger if point is outside of
  214. the box
  215. \param x X-Coordinate of the point to add to this box.
  216. \param y Y-Coordinate of the point to add to this box. */
  217. void addInternalPoint(T x, T y)
  218. {
  219. if (x>LowerRightCorner.X)
  220. LowerRightCorner.X = x;
  221. if (y>LowerRightCorner.Y)
  222. LowerRightCorner.Y = y;
  223. if (x<UpperLeftCorner.X)
  224. UpperLeftCorner.X = x;
  225. if (y<UpperLeftCorner.Y)
  226. UpperLeftCorner.Y = y;
  227. }
  228. //! Upper left corner
  229. position2d<T> UpperLeftCorner;
  230. //! Lower right corner
  231. position2d<T> LowerRightCorner;
  232. };
  233. //! Rectangle with float values
  234. typedef rect<f32> rectf;
  235. //! Rectangle with int values
  236. typedef rect<s32> recti;
  237. } // end namespace core
  238. } // end namespace irr
  239. #endif