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
00041 template <class Type> class LLRectBase
00042 {
00043 public:
00044 Type mLeft;
00045 Type mTop;
00046 Type mRight;
00047 Type mBottom;
00048
00049
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
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
00130
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
00136 end_x -= (Type)(clip_x);
00137 end_y -= (Type)(delta_y * ratio_x);
00138 }
00139 else
00140 {
00141
00142 end_x -= (Type)(delta_x * ratio_y);
00143 end_y -= (Type)clip_y;
00144 }
00145 }
00146
00147
00148
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
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
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