Rect.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Math/Vector4.h"
  24. namespace Urho3D
  25. {
  26. /// Two-dimensional bounding rectangle.
  27. /// @allfloats
  28. class URHO3D_API Rect
  29. {
  30. public:
  31. /// Construct an undefined rect.
  32. Rect() noexcept :
  33. min_(M_INFINITY, M_INFINITY),
  34. max_(-M_INFINITY, -M_INFINITY)
  35. {
  36. }
  37. /// Construct from minimum and maximum vectors.
  38. Rect(const Vector2& min, const Vector2& max) noexcept :
  39. min_(min),
  40. max_(max)
  41. {
  42. }
  43. /// Construct from coordinates.
  44. Rect(float left, float top, float right, float bottom) noexcept :
  45. min_(left, top),
  46. max_(right, bottom)
  47. {
  48. }
  49. /// Construct from a Vector4.
  50. explicit Rect(const Vector4& vector) noexcept :
  51. min_(vector.x_, vector.y_),
  52. max_(vector.z_, vector.w_)
  53. {
  54. }
  55. /// Construct from a float array.
  56. explicit Rect(const float* data) noexcept :
  57. min_(data[0], data[1]),
  58. max_(data[2], data[3])
  59. {
  60. }
  61. /// Copy-construct from another rect.
  62. Rect(const Rect& rect) noexcept = default;
  63. /// Assign from another rect.
  64. Rect& operator =(const Rect& rhs) noexcept = default;
  65. /// Test for equality with another rect.
  66. bool operator ==(const Rect& rhs) const { return min_ == rhs.min_ && max_ == rhs.max_; }
  67. /// Test for inequality with another rect.
  68. bool operator !=(const Rect& rhs) const { return min_ != rhs.min_ || max_ != rhs.max_; }
  69. /// Add another rect to this one inplace.
  70. Rect& operator +=(const Rect& rhs)
  71. {
  72. min_ += rhs.min_;
  73. max_ += rhs.max_;
  74. return *this;
  75. }
  76. /// Subtract another rect from this one inplace.
  77. Rect& operator -=(const Rect& rhs)
  78. {
  79. min_ -= rhs.min_;
  80. max_ -= rhs.max_;
  81. return *this;
  82. }
  83. /// Divide by scalar inplace.
  84. Rect& operator /=(float value)
  85. {
  86. min_ /= value;
  87. max_ /= value;
  88. return *this;
  89. }
  90. /// Multiply by scalar inplace.
  91. Rect& operator *=(float value)
  92. {
  93. min_ *= value;
  94. max_ *= value;
  95. return *this;
  96. }
  97. /// Divide by scalar.
  98. Rect operator /(float value) const
  99. {
  100. return Rect(min_ / value, max_ / value);
  101. }
  102. /// Multiply by scalar.
  103. Rect operator *(float value) const
  104. {
  105. return Rect(min_ * value, max_ * value);
  106. }
  107. /// Add another rect.
  108. Rect operator +(const Rect& rhs) const
  109. {
  110. return Rect(min_ + rhs.min_, max_ + rhs.max_);
  111. }
  112. /// Subtract another rect.
  113. Rect operator -(const Rect& rhs) const
  114. {
  115. return Rect(min_ - rhs.min_, max_ - rhs.max_);
  116. }
  117. /// Define from another rect.
  118. void Define(const Rect& rect)
  119. {
  120. min_ = rect.min_;
  121. max_ = rect.max_;
  122. }
  123. /// Define from minimum and maximum vectors.
  124. void Define(const Vector2& min, const Vector2& max)
  125. {
  126. min_ = min;
  127. max_ = max;
  128. }
  129. /// Define from a point.
  130. void Define(const Vector2& point)
  131. {
  132. min_ = max_ = point;
  133. }
  134. /// Merge a point.
  135. void Merge(const Vector2& point)
  136. {
  137. if (point.x_ < min_.x_)
  138. min_.x_ = point.x_;
  139. if (point.x_ > max_.x_)
  140. max_.x_ = point.x_;
  141. if (point.y_ < min_.y_)
  142. min_.y_ = point.y_;
  143. if (point.y_ > max_.y_)
  144. max_.y_ = point.y_;
  145. }
  146. /// Merge a rect.
  147. void Merge(const Rect& rect)
  148. {
  149. if (rect.min_.x_ < min_.x_)
  150. min_.x_ = rect.min_.x_;
  151. if (rect.min_.y_ < min_.y_)
  152. min_.y_ = rect.min_.y_;
  153. if (rect.max_.x_ > max_.x_)
  154. max_.x_ = rect.max_.x_;
  155. if (rect.max_.y_ > max_.y_)
  156. max_.y_ = rect.max_.y_;
  157. }
  158. /// Clear to undefined state.
  159. void Clear()
  160. {
  161. min_ = Vector2(M_INFINITY, M_INFINITY);
  162. max_ = Vector2(-M_INFINITY, -M_INFINITY);
  163. }
  164. /// Clip with another rect.
  165. void Clip(const Rect& rect);
  166. /// Return true if this rect is defined via a previous call to Define() or Merge().
  167. bool Defined() const
  168. {
  169. return min_.x_ != M_INFINITY;
  170. }
  171. /// Return center.
  172. /// @property
  173. Vector2 Center() const { return (max_ + min_) * 0.5f; }
  174. /// Return size.
  175. /// @property
  176. Vector2 Size() const { return max_ - min_; }
  177. /// Return half-size.
  178. /// @property
  179. Vector2 HalfSize() const { return (max_ - min_) * 0.5f; }
  180. /// Test for equality with another rect with epsilon.
  181. bool Equals(const Rect& rhs) const { return min_.Equals(rhs.min_) && max_.Equals(rhs.max_); }
  182. /// Test whether a point is inside.
  183. Intersection IsInside(const Vector2& point) const
  184. {
  185. if (point.x_ < min_.x_ || point.y_ < min_.y_ || point.x_ > max_.x_ || point.y_ > max_.y_)
  186. return OUTSIDE;
  187. else
  188. return INSIDE;
  189. }
  190. /// Test if another rect is inside, outside or intersects.
  191. Intersection IsInside(const Rect& rect) const
  192. {
  193. if (rect.max_.x_ < min_.x_ || rect.min_.x_ > max_.x_ || rect.max_.y_ < min_.y_ || rect.min_.y_ > max_.y_)
  194. return OUTSIDE;
  195. else if (rect.min_.x_ < min_.x_ || rect.max_.x_ > max_.x_ || rect.min_.y_ < min_.y_ || rect.max_.y_ > max_.y_)
  196. return INTERSECTS;
  197. else
  198. return INSIDE;
  199. }
  200. /// Return float data.
  201. const float* Data() const { return &min_.x_; }
  202. /// Return as a vector.
  203. Vector4 ToVector4() const { return Vector4(min_.x_, min_.y_, max_.x_, max_.y_); }
  204. /// Return as string.
  205. String ToString() const;
  206. /// Return left-top corner position.
  207. Vector2 Min() const { return min_; }
  208. /// Return right-bottom corner position.
  209. Vector2 Max() const { return max_; }
  210. /// Return left coordinate.
  211. /// @property
  212. float Left() const { return min_.x_; }
  213. /// Return top coordinate.
  214. /// @property
  215. float Top() const { return min_.y_; }
  216. /// Return right coordinate.
  217. /// @property
  218. float Right() const { return max_.x_; }
  219. /// Return bottom coordinate.
  220. /// @property
  221. float Bottom() const { return max_.y_; }
  222. /// Minimum vector.
  223. Vector2 min_;
  224. /// Maximum vector.
  225. Vector2 max_;
  226. /// Rect in the range (-1, -1) - (1, 1).
  227. static const Rect FULL;
  228. /// Rect in the range (0, 0) - (1, 1).
  229. static const Rect POSITIVE;
  230. /// Zero-sized rect.
  231. static const Rect ZERO;
  232. };
  233. /// Two-dimensional bounding rectangle with integer values.
  234. class URHO3D_API IntRect
  235. {
  236. public:
  237. /// Construct a zero rect.
  238. IntRect() noexcept :
  239. left_(0),
  240. top_(0),
  241. right_(0),
  242. bottom_(0)
  243. {
  244. }
  245. /// Construct from minimum and maximum vectors.
  246. IntRect(const IntVector2& min, const IntVector2& max) noexcept :
  247. left_(min.x_),
  248. top_(min.y_),
  249. right_(max.x_),
  250. bottom_(max.y_)
  251. {
  252. }
  253. /// Construct from coordinates.
  254. IntRect(int left, int top, int right, int bottom) noexcept :
  255. left_(left),
  256. top_(top),
  257. right_(right),
  258. bottom_(bottom)
  259. {
  260. }
  261. /// Construct from an int array.
  262. explicit IntRect(const int* data) noexcept :
  263. left_(data[0]),
  264. top_(data[1]),
  265. right_(data[2]),
  266. bottom_(data[3])
  267. {
  268. }
  269. /// Test for equality with another rect.
  270. bool operator ==(const IntRect& rhs) const
  271. {
  272. return left_ == rhs.left_ && top_ == rhs.top_ && right_ == rhs.right_ && bottom_ == rhs.bottom_;
  273. }
  274. /// Test for inequality with another rect.
  275. bool operator !=(const IntRect& rhs) const
  276. {
  277. return left_ != rhs.left_ || top_ != rhs.top_ || right_ != rhs.right_ || bottom_ != rhs.bottom_;
  278. }
  279. /// Add another rect to this one inplace.
  280. IntRect& operator +=(const IntRect& rhs)
  281. {
  282. left_ += rhs.left_;
  283. top_ += rhs.top_;
  284. right_ += rhs.right_;
  285. bottom_ += rhs.bottom_;
  286. return *this;
  287. }
  288. /// Subtract another rect from this one inplace.
  289. IntRect& operator -=(const IntRect& rhs)
  290. {
  291. left_ -= rhs.left_;
  292. top_ -= rhs.top_;
  293. right_ -= rhs.right_;
  294. bottom_ -= rhs.bottom_;
  295. return *this;
  296. }
  297. /// Divide by scalar inplace.
  298. IntRect& operator /=(float value)
  299. {
  300. left_ = static_cast<int>(left_ / value);
  301. top_ = static_cast<int>(top_ / value);
  302. right_ = static_cast<int>(right_ / value);
  303. bottom_ = static_cast<int>(bottom_ / value);
  304. return *this;
  305. }
  306. /// Multiply by scalar inplace.
  307. IntRect& operator *=(float value)
  308. {
  309. left_ = static_cast<int>(left_ * value);
  310. top_ = static_cast<int>(top_ * value);
  311. right_ = static_cast<int>(right_ * value);
  312. bottom_ = static_cast<int>(bottom_ * value);
  313. return *this;
  314. }
  315. /// Divide by scalar.
  316. IntRect operator /(float value) const
  317. {
  318. return {
  319. static_cast<int>(left_ / value), static_cast<int>(top_ / value),
  320. static_cast<int>(right_ / value), static_cast<int>(bottom_ / value)
  321. };
  322. }
  323. /// Multiply by scalar.
  324. IntRect operator *(float value) const
  325. {
  326. return {
  327. static_cast<int>(left_ * value), static_cast<int>(top_ * value),
  328. static_cast<int>(right_ * value), static_cast<int>(bottom_ * value)
  329. };
  330. }
  331. /// Add another rect.
  332. IntRect operator +(const IntRect& rhs) const
  333. {
  334. return {
  335. left_ + rhs.left_, top_ + rhs.top_,
  336. right_ + rhs.right_, bottom_ + rhs.bottom_
  337. };
  338. }
  339. /// Subtract another rect.
  340. IntRect operator -(const IntRect& rhs) const
  341. {
  342. return {
  343. left_ - rhs.left_, top_ - rhs.top_,
  344. right_ - rhs.right_, bottom_ - rhs.bottom_
  345. };
  346. }
  347. /// Return size.
  348. /// @property
  349. IntVector2 Size() const { return IntVector2(Width(), Height()); }
  350. /// Return width.
  351. /// @property
  352. int Width() const { return right_ - left_; }
  353. /// Return height.
  354. /// @property
  355. int Height() const { return bottom_ - top_; }
  356. /// Test whether a point is inside.
  357. Intersection IsInside(const IntVector2& point) const
  358. {
  359. if (point.x_ < left_ || point.y_ < top_ || point.x_ >= right_ || point.y_ >= bottom_)
  360. return OUTSIDE;
  361. else
  362. return INSIDE;
  363. }
  364. /// Test if another rect is inside, outside or intersects.
  365. Intersection IsInside(const IntRect& rect) const
  366. {
  367. if (rect.right_ < left_ || rect.left_ >= right_ || rect.bottom_ < top_ || rect.top_ >= bottom_)
  368. return OUTSIDE;
  369. else if (rect.left_ < left_ || rect.right_ > right_ || rect.top_ < top_ || rect.bottom_ > bottom_)
  370. return INTERSECTS;
  371. else
  372. return INSIDE;
  373. }
  374. /// Clip with another rect. Since IntRect does not have an undefined state
  375. /// like Rect, return (0, 0, 0, 0) if the result is empty.
  376. void Clip(const IntRect& rect);
  377. /// Merge a rect. If this rect was empty, become the other rect. If the
  378. /// other rect is empty, do nothing.
  379. void Merge(const IntRect& rect);
  380. /// Return integer data.
  381. const int* Data() const { return &left_; }
  382. /// Return as string.
  383. String ToString() const;
  384. /// Return left-top corner position.
  385. IntVector2 Min() const { return {left_, top_}; }
  386. /// Return right-bottom corner position.
  387. IntVector2 Max() const { return {right_, bottom_}; }
  388. /// Return left coordinate.
  389. int Left() const { return left_; }
  390. /// Return top coordinate.
  391. int Top() const { return top_; }
  392. /// Return right coordinate.
  393. int Right() const { return right_; }
  394. /// Return bottom coordinate.
  395. int Bottom() const { return bottom_; }
  396. /// Left coordinate.
  397. int left_;
  398. /// Top coordinate.
  399. int top_;
  400. /// Right coordinate.
  401. int right_;
  402. /// Bottom coordinate.
  403. int bottom_;
  404. /// Zero-sized rect.
  405. static const IntRect ZERO;
  406. };
  407. }