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 void set(Type left, Type top, Type right, Type bottom)
00156 {
00157 mLeft = left;
00158 mTop = top;
00159 mRight = right;
00160 mBottom = bottom;
00161 }
00162
00163
00164 void setOriginAndSize( Type left, Type bottom, Type width, Type height)
00165 {
00166 mLeft = left;
00167 mTop = bottom + height;
00168 mRight = left + width;
00169 mBottom = bottom;
00170 }
00171
00172
00173 void setLeftTopAndSize( Type left, Type top, Type width, Type height)
00174 {
00175 mLeft = left;
00176 mTop = top;
00177 mRight = left + width;
00178 mBottom = top - height;
00179 }
00180
00181 void setCenterAndSize(Type x, Type y, Type width, Type height)
00182 {
00183 mLeft = x - width/2;
00184 mTop = y + height/2;
00185 mRight = x + width/2;
00186 mBottom = y - height/2;
00187 }
00188
00189
00190 void translate(Type horiz, Type vertical)
00191 {
00192 mLeft += horiz;
00193 mRight += horiz;
00194 mTop += vertical;
00195 mBottom += vertical;
00196 }
00197
00198 void stretch( Type dx, Type dy)
00199 {
00200 mLeft -= dx;
00201 mRight += dx;
00202 mTop += dy;
00203 mBottom -= dy;
00204 makeValid();
00205 }
00206
00207 void stretch( Type delta )
00208 {
00209 stretch(delta, delta);
00210
00211 }
00212
00213 void makeValid()
00214 {
00215 mLeft = llmin(mLeft, mRight);
00216 mBottom = llmin(mBottom, mTop);
00217 }
00218
00219 void unionWith(const LLRectBase &other)
00220 {
00221 mLeft = llmin(mLeft, other.mLeft);
00222 mRight = llmax(mRight, other.mRight);
00223 mBottom = llmin(mBottom, other.mBottom);
00224 mTop = llmax(mTop, other.mTop);
00225 }
00226
00227 void intersectWith(const LLRectBase &other)
00228 {
00229 mLeft = llmax(mLeft, other.mLeft);
00230 mRight = llmin(mRight, other.mRight);
00231 mBottom = llmax(mBottom, other.mBottom);
00232 mTop = llmin(mTop, other.mTop);
00233 if (mLeft > mRight)
00234 {
00235 mLeft = mRight;
00236 }
00237 if (mBottom > mTop)
00238 {
00239 mBottom = mTop;
00240 }
00241 }
00242
00243 friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
00244 {
00245 s << "{ L " << rect.mLeft << " B " << rect.mBottom
00246 << " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
00247 return s;
00248 }
00249
00250 bool operator==(const LLRectBase &b)
00251 {
00252 return ((mLeft == b.mLeft) &&
00253 (mTop == b.mTop) &&
00254 (mRight == b.mRight) &&
00255 (mBottom == b.mBottom));
00256 }
00257
00258 bool operator!=(const LLRectBase &b)
00259 {
00260 return ((mLeft != b.mLeft) ||
00261 (mTop != b.mTop) ||
00262 (mRight != b.mRight) ||
00263 (mBottom != b.mBottom));
00264 }
00265
00266 static LLRectBase<Type> null;
00267 };
00268
00269 template <class Type> LLRectBase<Type> LLRectBase<Type>::null(0,0,0,0);
00270
00271 typedef LLRectBase<S32> LLRect;
00272 typedef LLRectBase<F32> LLRectf;
00273
00274 #endif