llrect.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /**
  2. * @file llrect.h
  3. * @brief A rectangle in GL coordinates, with bottom,left = 0,0
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLRECT_H
  33. #define LL_LLRECT_H
  34. #include <iostream>
  35. #include "llmath.h"
  36. #include "llsd.h"
  37. // Top > Bottom due to GL coords
  38. template <class Type> class LLRectBase
  39. {
  40. public:
  41. typedef Type tCoordType;
  42. LL_INLINE LLRectBase() noexcept
  43. : mLeft(0),
  44. mTop(0),
  45. mRight(0),
  46. mBottom(0)
  47. {
  48. }
  49. LL_INLINE LLRectBase(const LLRectBase& r) noexcept
  50. : mLeft(r.mLeft),
  51. mTop(r.mTop),
  52. mRight(r.mRight),
  53. mBottom(r.mBottom)
  54. {
  55. }
  56. LL_INLINE LLRectBase(Type left, Type top, Type right, Type bottom) noexcept
  57. : mLeft(left),
  58. mTop(top),
  59. mRight(right),
  60. mBottom(bottom)
  61. {
  62. }
  63. // Allow the use of the default C++11 move constructor and assignation
  64. LLRectBase(LLRectBase&& other) noexcept = default;
  65. LLRectBase& operator=(LLRectBase&& other) noexcept = default;
  66. LLRectBase& operator=(const LLRectBase& other) = default;
  67. LL_INLINE explicit LLRectBase(const LLSD& sd)
  68. {
  69. setValue(sd);
  70. }
  71. // Note: follows GL_QUAD conventions: the top and right edges are not
  72. // considered part of the rect
  73. LL_INLINE Type getWidth() const { return mRight - mLeft; }
  74. LL_INLINE Type getHeight() const { return mTop - mBottom; }
  75. LL_INLINE Type getCenterX() const { return (mLeft + mRight) / 2; }
  76. LL_INLINE Type getCenterY() const { return (mTop + mBottom) / 2; }
  77. LL_INLINE void setValue(const LLSD& sd)
  78. {
  79. mLeft = (Type)sd[0].asInteger();
  80. mTop = (Type)sd[1].asInteger();
  81. mRight = (Type)sd[2].asInteger();
  82. mBottom = (Type)sd[3].asInteger();
  83. }
  84. LL_INLINE LLSD getValue() const
  85. {
  86. LLSD ret;
  87. ret[0] = mLeft;
  88. ret[1] = mTop;
  89. ret[2] = mRight;
  90. ret[3] = mBottom;
  91. return ret;
  92. }
  93. // Note: follows GL_QUAD conventions: the top and right edges are not
  94. // considered part of the rect
  95. LL_INLINE bool pointInRect(const Type x, const Type y) const
  96. {
  97. return mLeft <= x && x < mRight && mBottom <= y && y < mTop;
  98. }
  99. // Note: follows GL_QUAD conventions: the top and right edges are not
  100. // considered part of the rect
  101. LL_INLINE bool localPointInRect(const Type x, const Type y) const
  102. {
  103. return 0 <= x && x < getWidth() && 0 <= y && y < getHeight();
  104. }
  105. LL_INLINE void clampPointToRect(Type& x, Type& y)
  106. {
  107. x = llclamp(x, mLeft, mRight);
  108. y = llclamp(y, mBottom, mTop);
  109. }
  110. void clipPointToRect(const Type start_x, const Type start_y,
  111. Type& end_x, Type& end_y)
  112. {
  113. if (!pointInRect(start_x, start_y))
  114. {
  115. return;
  116. }
  117. Type clip_x = 0;
  118. Type clip_y = 0;
  119. Type delta_x = end_x - start_x;
  120. Type delta_y = end_y - start_y;
  121. if (end_x > mRight) clip_x = end_x - mRight;
  122. if (end_x < mLeft) clip_x = end_x - mLeft;
  123. if (end_y > mTop) clip_y = end_y - mTop;
  124. if (end_y < mBottom) clip_y = end_y - mBottom;
  125. // clip_? and delta_? should have same sign, since starting point is in
  126. // rect so ratios will be positive
  127. F32 ratio_x = delta_x ? (F32)clip_x / (F32)delta_x : 0.f;
  128. F32 ratio_y = delta_y ? (F32)clip_y / (F32)delta_y : 0.f;
  129. if (ratio_x > ratio_y)
  130. {
  131. // Clip along x direction
  132. end_x -= (Type)clip_x;
  133. end_y -= (Type)(delta_y * ratio_x);
  134. }
  135. else
  136. {
  137. // Clip along y direction
  138. end_x -= (Type)(delta_x * ratio_y);
  139. end_y -= (Type)clip_y;
  140. }
  141. }
  142. // Note: does NOT follow GL_QUAD conventions: the top and right edges ARE
  143. // considered part of the rect. Returns true if any part of rect is is
  144. // inside this LLRect
  145. LL_INLINE bool overlaps(const LLRectBase& rect) const
  146. {
  147. return !(mLeft > rect.mRight || mRight < rect.mLeft ||
  148. mBottom > rect.mTop || mTop < rect.mBottom);
  149. }
  150. LL_INLINE bool contains(const LLRectBase& rect) const
  151. {
  152. return mLeft <= rect.mLeft && mRight >= rect.mRight &&
  153. mBottom <= rect.mBottom && mTop >= rect.mTop;
  154. }
  155. LL_INLINE LLRectBase& set(Type left, Type top, Type right, Type bottom)
  156. {
  157. mLeft = left;
  158. mTop = top;
  159. mRight = right;
  160. mBottom = bottom;
  161. return *this;
  162. }
  163. // Note: follows GL_QUAD conventions: the top and right edges are not
  164. // considered part of the rect
  165. LL_INLINE LLRectBase& setOriginAndSize(Type left, Type bottom, Type width,
  166. Type height)
  167. {
  168. mLeft = left;
  169. mTop = bottom + height;
  170. mRight = left + width;
  171. mBottom = bottom;
  172. return *this;
  173. }
  174. // Note: follows GL_QUAD conventions: the top and right edges are not
  175. // considered part of the rect
  176. LL_INLINE LLRectBase& setLeftTopAndSize(Type left, Type top, Type width,
  177. Type height)
  178. {
  179. mLeft = left;
  180. mTop = top;
  181. mRight = left + width;
  182. mBottom = top - height;
  183. return *this;
  184. }
  185. LL_INLINE LLRectBase& setCenterAndSize(Type x, Type y, Type width,
  186. Type height)
  187. {
  188. // width and height could be odd, so favor top, right with extra pixel
  189. mLeft = x - width / 2;
  190. mBottom = y - height / 2;
  191. mTop = mBottom + height;
  192. mRight = mLeft + width;
  193. return *this;
  194. }
  195. LL_INLINE LLRectBase& translate(Type horiz, Type vertical)
  196. {
  197. mLeft += horiz;
  198. mRight += horiz;
  199. mTop += vertical;
  200. mBottom += vertical;
  201. return *this;
  202. }
  203. LL_INLINE LLRectBase& stretch(Type dx, Type dy)
  204. {
  205. mLeft -= dx;
  206. mRight += dx;
  207. mTop += dy;
  208. mBottom -= dy;
  209. return makeValid();
  210. }
  211. LL_INLINE LLRectBase& stretch(Type delta)
  212. {
  213. stretch(delta, delta);
  214. return *this;
  215. }
  216. LL_INLINE LLRectBase& makeValid()
  217. {
  218. mLeft = llmin(mLeft, mRight);
  219. mBottom = llmin(mBottom, mTop);
  220. return *this;
  221. }
  222. LL_INLINE bool isValid() const
  223. {
  224. return mLeft <= mRight && mBottom <= mTop;
  225. }
  226. LL_INLINE bool isEmpty() const
  227. {
  228. return mLeft == mRight || mBottom == mTop;
  229. }
  230. LL_INLINE bool notEmpty() const
  231. {
  232. return !isEmpty();
  233. }
  234. LL_INLINE void unionWith(const LLRectBase& other)
  235. {
  236. mLeft = llmin(mLeft, other.mLeft);
  237. mRight = llmax(mRight, other.mRight);
  238. mBottom = llmin(mBottom, other.mBottom);
  239. mTop = llmax(mTop, other.mTop);
  240. }
  241. LL_INLINE void intersectWith(const LLRectBase& other)
  242. {
  243. mLeft = llmax(mLeft, other.mLeft);
  244. mRight = llmin(mRight, other.mRight);
  245. mBottom = llmax(mBottom, other.mBottom);
  246. mTop = llmin(mTop, other.mTop);
  247. if (mLeft > mRight)
  248. {
  249. mLeft = mRight;
  250. }
  251. if (mBottom > mTop)
  252. {
  253. mBottom = mTop;
  254. }
  255. }
  256. friend std::ostream& operator<<(std::ostream& s, const LLRectBase& rect)
  257. {
  258. s << "{ L " << rect.mLeft << " B " << rect.mBottom
  259. << " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
  260. return s;
  261. }
  262. LL_INLINE bool operator==(const LLRectBase& b) const
  263. {
  264. return mLeft == b.mLeft && mTop == b.mTop && mRight == b.mRight &&
  265. mBottom == b.mBottom;
  266. }
  267. LL_INLINE bool operator!=(const LLRectBase& b) const
  268. {
  269. return mLeft != b.mLeft || mTop != b.mTop || mRight != b.mRight ||
  270. mBottom != b.mBottom;
  271. }
  272. public:
  273. Type mLeft;
  274. Type mTop;
  275. Type mRight;
  276. Type mBottom;
  277. static LLRectBase<Type> null;
  278. };
  279. template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0, 0, 0, 0);
  280. typedef LLRectBase<S32> LLRect;
  281. typedef LLRectBase<F32> LLRectf;
  282. #endif