llrect.h

Go to the documentation of this file.
00001 
00033 #ifndef LL_LLRECT_H
00034 #define LL_LLRECT_H
00035 
00036 #include <iostream>
00037 #include "llmath.h"
00038 #include "llsd.h"
00039 
00040 // Top > Bottom due to GL coords
00041 template <class Type> class LLRectBase
00042 {
00043 public:
00044         Type            mLeft;
00045         Type            mTop;
00046         Type            mRight;
00047         Type            mBottom;
00048 
00049         // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
00050         Type            getWidth()      const { return mRight - mLeft; }
00051         Type            getHeight()     const { return mTop - mBottom; }
00052         Type            getCenterX() const { return (mLeft + mRight) / 2; }
00053         Type            getCenterY() const { return (mTop + mBottom) / 2; }
00054 
00055         LLRectBase():   mLeft(0), mTop(0), mRight(0), mBottom(0)
00056         {}
00057 
00058         LLRectBase(const LLRectBase &r):
00059         mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom)
00060         {}
00061 
00062         LLRectBase(Type left, Type top, Type right, Type bottom):
00063         mLeft(left), mTop(top), mRight(right), mBottom(bottom)
00064         {}
00065 
00066         LLRectBase(const LLSD& sd)
00067         {
00068                 setValue(sd);
00069         }
00070 
00071         const LLRectBase& operator=(const LLSD& sd)
00072         {
00073                 setValue(sd);
00074                 return *this;
00075         }
00076 
00077         void setValue(const LLSD& sd)
00078         {
00079                 mLeft = sd[0].asInteger(); 
00080                 mTop = sd[1].asInteger();
00081                 mRight = sd[2].asInteger();
00082                 mBottom = sd[3].asInteger();
00083         }
00084 
00085         LLSD getValue() const
00086         {
00087                 LLSD ret;
00088                 ret[0] = mLeft;
00089                 ret[1] = mTop;
00090                 ret[2] = mRight;
00091                 ret[3] = mBottom;
00092                 return ret;
00093         }
00094 
00095         // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
00096         BOOL            pointInRect(const Type x, const Type y) const
00097         {
00098                 return  mLeft <= x && x < mRight &&
00099                                 mBottom <= y && y < mTop;
00100         }
00101 
00103         BOOL            localPointInRect(const Type x, const Type y) const
00104         {
00105                 return  0 <= x && x < getWidth() &&
00106                                 0 <= y && y < getHeight();
00107         }
00108 
00109         void            clampPointToRect(Type& x, Type& y)
00110         {
00111                 x = llclamp(x, mLeft, mRight);
00112                 y = llclamp(y, mBottom, mTop);
00113         }
00114 
00115         void            clipPointToRect(const Type start_x, const Type start_y, Type& end_x, Type& end_y)
00116         {
00117                 if (!pointInRect(start_x, start_y))
00118                 {
00119                         return;
00120                 }
00121                 Type clip_x = 0;
00122                 Type clip_y = 0;
00123                 Type delta_x = end_x - start_x;
00124                 Type delta_y = end_y - start_y;
00125                 if (end_x > mRight) clip_x = end_x - mRight;
00126                 if (end_x < mLeft) clip_x = end_x - mLeft;
00127                 if (end_y > mTop) clip_y = end_y - mTop;
00128                 if (end_y < mBottom) clip_y = end_y - mBottom;
00129                 // clip_? and delta_? should have same sign, since starting point is in rect
00130                 // so ratios will be positive
00131                 F32 ratio_x = ((F32)clip_x / (F32)delta_x);
00132                 F32 ratio_y = ((F32)clip_y / (F32)delta_y);
00133                 if (ratio_x > ratio_y)
00134                 {
00135                         // clip along x direction
00136                         end_x -= (Type)(clip_x);
00137                         end_y -= (Type)(delta_y * ratio_x);
00138                 }
00139                 else
00140                 {
00141                         // clip along y direction
00142                         end_x -= (Type)(delta_x * ratio_y);
00143                         end_y -= (Type)clip_y;
00144                 }
00145         }
00146 
00147         // Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect
00148         // returns TRUE if any part of rect is is inside this LLRect
00149         BOOL            rectInRect(const LLRectBase* rect) const
00150         {
00151                 return mLeft <= rect->mRight && rect->mLeft <= mRight && 
00152                            mBottom <= rect->mTop && rect->mBottom <= mTop ;
00153         }
00154 
00155         LLRectBase& set(Type left, Type top, Type right, Type bottom)
00156         {
00157                 mLeft = left;
00158                 mTop = top;
00159                 mRight = right;
00160                 mBottom = bottom;
00161                 return *this;
00162         }
00163 
00164         // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
00165         LLRectBase& setOriginAndSize( Type left, Type bottom, Type width, Type height)
00166         {
00167                 mLeft = left;
00168                 mTop = bottom + height;
00169                 mRight = left + width;
00170                 mBottom = bottom;
00171                 return *this;
00172         }
00173 
00174         // Note: follows GL_QUAD conventions: the top and right edges are not considered part of the rect
00175         LLRectBase& setLeftTopAndSize( Type left, Type top, Type width, Type height)
00176         {
00177                 mLeft = left;
00178                 mTop = top;
00179                 mRight = left + width;
00180                 mBottom = top - height;
00181                 return *this;
00182         }
00183 
00184         LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
00185         {
00186                 mLeft = x - width/2;
00187                 mTop = y + height/2;
00188                 mRight = x + width/2;
00189                 mBottom = y - height/2;
00190                 return *this;
00191         }
00192 
00193 
00194         LLRectBase& translate(Type horiz, Type vertical)
00195         {
00196                 mLeft += horiz;
00197                 mRight += horiz;
00198                 mTop += vertical;
00199                 mBottom += vertical;
00200                 return *this;
00201         }
00202 
00203         LLRectBase& stretch( Type dx, Type dy)
00204         {
00205                 mLeft -= dx;
00206                 mRight += dx;
00207                 mTop += dy;
00208                 mBottom -= dy;
00209                 return makeValid();
00210         }
00211         
00212         LLRectBase& stretch( Type delta )
00213         {
00214                 stretch(delta, delta);
00215                 return *this;
00216         }
00217         
00218         LLRectBase& makeValid()
00219         {
00220                 mLeft = llmin(mLeft, mRight);
00221                 mBottom = llmin(mBottom, mTop);
00222                 return *this;
00223         }
00224 
00225         bool isNull() const
00226         {
00227                 return mLeft == mRight || mBottom == mTop;
00228         }
00229 
00230         bool notNull() const
00231         {
00232                 return !isNull();
00233         }
00234 
00235         LLRectBase& unionWith(const LLRectBase &other)
00236         {
00237                 mLeft = llmin(mLeft, other.mLeft);
00238                 mRight = llmax(mRight, other.mRight);
00239                 mBottom = llmin(mBottom, other.mBottom);
00240                 mTop = llmax(mTop, other.mTop);
00241                 return *this;
00242         }
00243 
00244         LLRectBase& intersectWith(const LLRectBase &other)
00245         {
00246                 mLeft = llmax(mLeft, other.mLeft);
00247                 mRight = llmin(mRight, other.mRight);
00248                 mBottom = llmax(mBottom, other.mBottom);
00249                 mTop = llmin(mTop, other.mTop);
00250                 if (mLeft > mRight)
00251                 {
00252                         mLeft = mRight;
00253                 }
00254                 if (mBottom > mTop)
00255                 {
00256                         mBottom = mTop;
00257                 }
00258                 return *this;
00259         }
00260 
00261         friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
00262         {
00263                 s << "{ L " << rect.mLeft << " B " << rect.mBottom
00264                         << " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
00265                 return s;
00266         }
00267 
00268         bool operator==(const LLRectBase &b)
00269         {
00270                 return ((mLeft == b.mLeft) &&
00271                                 (mTop == b.mTop) &&
00272                                 (mRight == b.mRight) &&
00273                                 (mBottom == b.mBottom));
00274         }
00275 
00276         bool operator!=(const LLRectBase &b)
00277         {
00278                 return ((mLeft != b.mLeft) ||
00279                                 (mTop != b.mTop) ||
00280                                 (mRight != b.mRight) ||
00281                                 (mBottom != b.mBottom));
00282         }
00283 
00284         static LLRectBase<Type> null;
00285 };
00286 
00287 template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0,0,0,0);
00288 
00289 typedef LLRectBase<S32> LLRect;
00290 typedef LLRectBase<F32> LLRectf;
00291 
00292 #endif

Generated on Fri May 16 08:32:15 2008 for SecondLife by  doxygen 1.5.5