PageRenderTime 47ms CodeModel.GetById 1ms app.highlight 41ms RepoModel.GetById 1ms 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
  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
 27
 28#ifndef LL_LLRECT_H
 29#define LL_LLRECT_H
 30
 31#include <iostream>
 32#include "llmath.h"
 33#include "llsd.h"
 34
 35// Top > Bottom due to GL coords
 36template <class Type> class LLRectBase
 37{
 38public:
 39	typedef	Type tCoordType;
 40	Type		mLeft;
 41	Type		mTop;
 42	Type		mRight;
 43	Type		mBottom;
 44
 45	// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
 46	Type		getWidth()	const { return mRight - mLeft; }
 47	Type		getHeight()	const { return mTop - mBottom; }
 48	Type		getCenterX() const { return (mLeft + mRight) / 2; }
 49	Type		getCenterY() const { return (mTop + mBottom) / 2; }
 50
 51	LLRectBase():	mLeft(0), mTop(0), mRight(0), mBottom(0)
 52	{}
 53
 54	LLRectBase(const LLRectBase &r):
 55	mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom)
 56	{}
 57
 58	LLRectBase(Type left, Type top, Type right, Type bottom):
 59	mLeft(left), mTop(top), mRight(right), mBottom(bottom)
 60	{}
 61
 62	explicit LLRectBase(const LLSD& sd)
 63	{
 64		setValue(sd);
 65	}
 66
 67	void setValue(const LLSD& sd)
 68	{
 69		mLeft = (Type)sd[0].asInteger(); 
 70		mTop = (Type)sd[1].asInteger();
 71		mRight = (Type)sd[2].asInteger();
 72		mBottom = (Type)sd[3].asInteger();
 73	}
 74
 75	LLSD getValue() const
 76	{
 77		LLSD ret;
 78		ret[0] = mLeft;
 79		ret[1] = mTop;
 80		ret[2] = mRight;
 81		ret[3] = mBottom;
 82		return ret;
 83	}
 84
 85	// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
 86	BOOL		pointInRect(const Type x, const Type y) const
 87	{
 88		return  mLeft <= x && x < mRight &&
 89				mBottom <= y && y < mTop;
 90	}
 91
 92	//// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
 93	BOOL		localPointInRect(const Type x, const Type y) const
 94	{
 95		return  0 <= x && x < getWidth() &&
 96				0 <= y && y < getHeight();
 97	}
 98
 99	void		clampPointToRect(Type& x, Type& y)
100	{
101		x = llclamp(x, mLeft, mRight);
102		y = llclamp(y, mBottom, mTop);
103	}
104
105	void		clipPointToRect(const Type start_x, const Type start_y, Type& end_x, Type& end_y)
106	{
107		if (!pointInRect(start_x, start_y))
108		{
109			return;
110		}
111		Type clip_x = 0;
112		Type clip_y = 0;
113		Type delta_x = end_x - start_x;
114		Type delta_y = end_y - start_y;
115		if (end_x > mRight) clip_x = end_x - mRight;
116		if (end_x < mLeft) clip_x = end_x - mLeft;
117		if (end_y > mTop) clip_y = end_y - mTop;
118		if (end_y < mBottom) clip_y = end_y - mBottom;
119		// clip_? and delta_? should have same sign, since starting point is in rect
120		// so ratios will be positive
121		F32 ratio_x = ((F32)clip_x / (F32)delta_x);
122		F32 ratio_y = ((F32)clip_y / (F32)delta_y);
123		if (ratio_x > ratio_y)
124		{
125			// clip along x direction
126			end_x -= (Type)(clip_x);
127			end_y -= (Type)(delta_y * ratio_x);
128		}
129		else
130		{
131			// clip along y direction
132			end_x -= (Type)(delta_x * ratio_y);
133			end_y -= (Type)clip_y;
134		}
135	}
136
137	// Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect
138	// returns TRUE if any part of rect is is inside this LLRect
139	BOOL		overlaps(const LLRectBase& rect) const
140	{
141		return !(mLeft > rect.mRight 
142			|| mRight < rect.mLeft
143			|| mBottom > rect.mTop 
144			|| mTop < rect.mBottom);
145	}
146
147	BOOL		contains(const LLRectBase& rect) const
148	{
149		return mLeft <= rect.mLeft
150			&& mRight >= rect.mRight
151			&& mBottom <= rect.mBottom
152			&& mTop >= rect.mTop;
153	}
154
155	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
164	// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
165	LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height)
166	{
167		mLeft = left;
168		mTop = bottom + height;
169		mRight = left + width;
170		mBottom = bottom;
171		return *this;
172	}
173
174	// Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
175	LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height)
176	{
177		mLeft = left;
178		mTop = top;
179		mRight = left + width;
180		mBottom = top - height;
181		return *this;
182	}
183
184	LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
185	{
186		// width and height could be odd, so favor top, right with extra pixel
187		mLeft = x - width/2;
188		mBottom = y - height/2;
189		mTop = mBottom + height;
190		mRight = mLeft + width;
191		return *this;
192	}
193
194
195	LLRectBase& translate(Type horiz, Type vertical)
196	{
197		mLeft += horiz;
198		mRight += horiz;
199		mTop += vertical;
200		mBottom += vertical;
201		return *this;
202	}
203
204	LLRectBase& stretch( Type dx, Type dy)
205	{
206		mLeft -= dx;
207		mRight += dx;
208		mTop += dy;
209		mBottom -= dy;
210		return makeValid();
211	}
212	
213	LLRectBase& stretch( Type delta )
214	{
215		stretch(delta, delta);
216		return *this;
217	}
218	
219	LLRectBase& makeValid()
220	{
221		mLeft = llmin(mLeft, mRight);
222		mBottom = llmin(mBottom, mTop);
223		return *this;
224	}
225
226	bool isValid() const
227	{
228		return mLeft <= mRight && mBottom <= mTop;
229	}
230
231	bool isEmpty() const
232	{
233		return mLeft == mRight || mBottom == mTop;
234	}
235
236	bool notEmpty() const
237	{
238		return !isEmpty();
239	}
240
241	void unionWith(const LLRectBase &other)
242	{
243		mLeft = llmin(mLeft, other.mLeft);
244		mRight = llmax(mRight, other.mRight);
245		mBottom = llmin(mBottom, other.mBottom);
246		mTop = llmax(mTop, other.mTop);
247	}
248
249	void intersectWith(const LLRectBase &other)
250	{
251		mLeft = llmax(mLeft, other.mLeft);
252		mRight = llmin(mRight, other.mRight);
253		mBottom = llmax(mBottom, other.mBottom);
254		mTop = llmin(mTop, other.mTop);
255		if (mLeft > mRight)
256		{
257			mLeft = mRight;
258		}
259		if (mBottom > mTop)
260		{
261			mBottom = mTop;
262		}
263	}
264
265	friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
266	{
267		s << "{ L " << rect.mLeft << " B " << rect.mBottom
268			<< " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
269		return s;
270	}
271	
272	bool operator==(const LLRectBase &b) const
273	{
274		return ((mLeft == b.mLeft) &&
275				(mTop == b.mTop) &&
276				(mRight == b.mRight) &&
277				(mBottom == b.mBottom));
278	}
279
280	bool operator!=(const LLRectBase &b) const
281	{
282		return ((mLeft != b.mLeft) ||
283				(mTop != b.mTop) ||
284				(mRight != b.mRight) ||
285				(mBottom != b.mBottom));
286	}
287
288	static LLRectBase<Type> null;
289};
290
291template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0,0,0,0);
292
293typedef LLRectBase<S32> LLRect;
294typedef LLRectBase<F32> LLRectf;
295
296#endif