PageRenderTime 37ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmath/llrect.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 296 lines | 220 code | 38 blank | 38 comment | 30 complexity | 49881eecaa12b56a7af1af3c3ffcc907 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llrect.h
  3. * @brief A rectangle in GL coordinates, with bottom,left = 0,0
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LLRECT_H
  27. #define LL_LLRECT_H
  28. #include <iostream>
  29. #include "llmath.h"
  30. #include "llsd.h"
  31. // Top > Bottom due to GL coords
  32. template <class Type> class LLRectBase
  33. {
  34. public:
  35. typedef Type tCoordType;
  36. Type mLeft;
  37. Type mTop;
  38. Type mRight;
  39. Type mBottom;
  40. // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
  41. Type getWidth() const { return mRight - mLeft; }
  42. Type getHeight() const { return mTop - mBottom; }
  43. Type getCenterX() const { return (mLeft + mRight) / 2; }
  44. Type getCenterY() const { return (mTop + mBottom) / 2; }
  45. LLRectBase(): mLeft(0), mTop(0), mRight(0), mBottom(0)
  46. {}
  47. LLRectBase(const LLRectBase &r):
  48. mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom)
  49. {}
  50. LLRectBase(Type left, Type top, Type right, Type bottom):
  51. mLeft(left), mTop(top), mRight(right), mBottom(bottom)
  52. {}
  53. explicit LLRectBase(const LLSD& sd)
  54. {
  55. setValue(sd);
  56. }
  57. void setValue(const LLSD& sd)
  58. {
  59. mLeft = (Type)sd[0].asInteger();
  60. mTop = (Type)sd[1].asInteger();
  61. mRight = (Type)sd[2].asInteger();
  62. mBottom = (Type)sd[3].asInteger();
  63. }
  64. LLSD getValue() const
  65. {
  66. LLSD ret;
  67. ret[0] = mLeft;
  68. ret[1] = mTop;
  69. ret[2] = mRight;
  70. ret[3] = mBottom;
  71. return ret;
  72. }
  73. // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
  74. BOOL pointInRect(const Type x, const Type y) const
  75. {
  76. return mLeft <= x && x < mRight &&
  77. mBottom <= y && y < mTop;
  78. }
  79. //// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
  80. BOOL localPointInRect(const Type x, const Type y) const
  81. {
  82. return 0 <= x && x < getWidth() &&
  83. 0 <= y && y < getHeight();
  84. }
  85. void clampPointToRect(Type& x, Type& y)
  86. {
  87. x = llclamp(x, mLeft, mRight);
  88. y = llclamp(y, mBottom, mTop);
  89. }
  90. void clipPointToRect(const Type start_x, const Type start_y, Type& end_x, Type& end_y)
  91. {
  92. if (!pointInRect(start_x, start_y))
  93. {
  94. return;
  95. }
  96. Type clip_x = 0;
  97. Type clip_y = 0;
  98. Type delta_x = end_x - start_x;
  99. Type delta_y = end_y - start_y;
  100. if (end_x > mRight) clip_x = end_x - mRight;
  101. if (end_x < mLeft) clip_x = end_x - mLeft;
  102. if (end_y > mTop) clip_y = end_y - mTop;
  103. if (end_y < mBottom) clip_y = end_y - mBottom;
  104. // clip_? and delta_? should have same sign, since starting point is in rect
  105. // so ratios will be positive
  106. F32 ratio_x = ((F32)clip_x / (F32)delta_x);
  107. F32 ratio_y = ((F32)clip_y / (F32)delta_y);
  108. if (ratio_x > ratio_y)
  109. {
  110. // clip along x direction
  111. end_x -= (Type)(clip_x);
  112. end_y -= (Type)(delta_y * ratio_x);
  113. }
  114. else
  115. {
  116. // clip along y direction
  117. end_x -= (Type)(delta_x * ratio_y);
  118. end_y -= (Type)clip_y;
  119. }
  120. }
  121. // Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect
  122. // returns TRUE if any part of rect is is inside this LLRect
  123. BOOL overlaps(const LLRectBase& rect) const
  124. {
  125. return !(mLeft > rect.mRight
  126. || mRight < rect.mLeft
  127. || mBottom > rect.mTop
  128. || mTop < rect.mBottom);
  129. }
  130. BOOL contains(const LLRectBase& rect) const
  131. {
  132. return mLeft <= rect.mLeft
  133. && mRight >= rect.mRight
  134. && mBottom <= rect.mBottom
  135. && mTop >= rect.mTop;
  136. }
  137. LLRectBase& set(Type left, Type top, Type right, Type bottom)
  138. {
  139. mLeft = left;
  140. mTop = top;
  141. mRight = right;
  142. mBottom = bottom;
  143. return *this;
  144. }
  145. // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
  146. LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height)
  147. {
  148. mLeft = left;
  149. mTop = bottom + height;
  150. mRight = left + width;
  151. mBottom = bottom;
  152. return *this;
  153. }
  154. // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
  155. LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height)
  156. {
  157. mLeft = left;
  158. mTop = top;
  159. mRight = left + width;
  160. mBottom = top - height;
  161. return *this;
  162. }
  163. LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
  164. {
  165. // width and height could be odd, so favor top, right with extra pixel
  166. mLeft = x - width/2;
  167. mBottom = y - height/2;
  168. mTop = mBottom + height;
  169. mRight = mLeft + width;
  170. return *this;
  171. }
  172. LLRectBase& translate(Type horiz, Type vertical)
  173. {
  174. mLeft += horiz;
  175. mRight += horiz;
  176. mTop += vertical;
  177. mBottom += vertical;
  178. return *this;
  179. }
  180. LLRectBase& stretch( Type dx, Type dy)
  181. {
  182. mLeft -= dx;
  183. mRight += dx;
  184. mTop += dy;
  185. mBottom -= dy;
  186. return makeValid();
  187. }
  188. LLRectBase& stretch( Type delta )
  189. {
  190. stretch(delta, delta);
  191. return *this;
  192. }
  193. LLRectBase& makeValid()
  194. {
  195. mLeft = llmin(mLeft, mRight);
  196. mBottom = llmin(mBottom, mTop);
  197. return *this;
  198. }
  199. bool isValid() const
  200. {
  201. return mLeft <= mRight && mBottom <= mTop;
  202. }
  203. bool isEmpty() const
  204. {
  205. return mLeft == mRight || mBottom == mTop;
  206. }
  207. bool notEmpty() const
  208. {
  209. return !isEmpty();
  210. }
  211. void unionWith(const LLRectBase &other)
  212. {
  213. mLeft = llmin(mLeft, other.mLeft);
  214. mRight = llmax(mRight, other.mRight);
  215. mBottom = llmin(mBottom, other.mBottom);
  216. mTop = llmax(mTop, other.mTop);
  217. }
  218. void intersectWith(const LLRectBase &other)
  219. {
  220. mLeft = llmax(mLeft, other.mLeft);
  221. mRight = llmin(mRight, other.mRight);
  222. mBottom = llmax(mBottom, other.mBottom);
  223. mTop = llmin(mTop, other.mTop);
  224. if (mLeft > mRight)
  225. {
  226. mLeft = mRight;
  227. }
  228. if (mBottom > mTop)
  229. {
  230. mBottom = mTop;
  231. }
  232. }
  233. friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
  234. {
  235. s << "{ L " << rect.mLeft << " B " << rect.mBottom
  236. << " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
  237. return s;
  238. }
  239. bool operator==(const LLRectBase &b) const
  240. {
  241. return ((mLeft == b.mLeft) &&
  242. (mTop == b.mTop) &&
  243. (mRight == b.mRight) &&
  244. (mBottom == b.mBottom));
  245. }
  246. bool operator!=(const LLRectBase &b) const
  247. {
  248. return ((mLeft != b.mLeft) ||
  249. (mTop != b.mTop) ||
  250. (mRight != b.mRight) ||
  251. (mBottom != b.mBottom));
  252. }
  253. static LLRectBase<Type> null;
  254. };
  255. template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0,0,0,0);
  256. typedef LLRectBase<S32> LLRect;
  257. typedef LLRectBase<F32> LLRectf;
  258. #endif