00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __IAIRect__
00019 #define __IAIRect__
00020
00021
00022
00023
00024
00025 #include "AIBasicTypes.h"
00026 #include <cmath>
00027 #include <cfloat>
00028 #include <cstdlib>
00029 #include "AIBasicUtilities.h"
00030
00031 namespace ai
00032 {
00033 template<typename T>
00034 struct Absolute
00035 {
00036 static T Absolute_Val(T a){
00037 return ::abs(a);
00038 }
00039 };
00040
00041 template<>
00042 struct Absolute<AIReal>
00043 {
00044 static AIReal Absolute_Val(AIReal a){
00045 return ::fabs(a);
00046 }
00047 };
00048
00049 namespace RectTraits
00050 {
00051 template<typename T>
00052 struct RectStruct_Traits
00053 {
00054
00055 };
00056 template<>
00057 struct RectStruct_Traits <AIRect>
00058 {
00059 typedef AIPoint Point_t;
00060
00061
00062 #ifdef WIN_ENV
00063 typedef ai::int32 Coordinates_t;
00064 #endif
00065 #ifdef MAC_ENV
00066 typedef short Coordinates_t;
00067 #endif
00068 #ifdef LINUX_ENV
00069 typedef short Coordinates_t;
00070 #endif
00071 typedef Absolute<Coordinates_t> ABS_t;
00072 };
00073 template<>
00074 struct RectStruct_Traits <AIRealRect>
00075 {
00076 typedef AIRealPoint Point_t;
00077 typedef AIReal Coordinates_t;
00078 typedef Absolute<Coordinates_t> ABS_t;
00079 };
00080 }
00081 }
00082
00083
00084
00085
00086 template <typename T>
00087 class IAIRectImpl : public T
00088 {
00089 private:
00090 typedef typename ai::RectTraits::RectStruct_Traits<T>::ABS_t AbsoluteFunction;
00091 typedef typename ai::RectTraits::RectStruct_Traits<T>::Point_t PointType;
00092 typedef typename ai::RectTraits::RectStruct_Traits<T>::Coordinates_t CoordinateType;
00093 public:
00094 IAIRectImpl(){}
00095 IAIRectImpl(const T& rect)
00096 {
00097 this->left = rect.left;
00098 this->top = rect.top;
00099 this->right = rect.right;
00100 this->bottom = rect.bottom;
00101 }
00102
00103 IAIRectImpl(const PointType& a)
00104 {
00105 this->left = a.h;
00106 this->right = a.h;
00107 this->top = a.v;
00108 this->bottom = a.v;
00109 }
00110
00111 IAIRectImpl(const PointType& a, const PointType& b)
00112 {
00113 this->left = ai::Min(a.h, b.h);
00114 this->right = ai::Max(a.h, b.h);
00115 this->top = ai::Min(a.v, b.v);
00116 this->bottom = ai::Max(a.v, b.v);
00117 }
00118
00119 IAIRectImpl(CoordinateType l, CoordinateType t, CoordinateType r, CoordinateType b)
00120 {
00121 this->left = l;
00122 this->top = t;
00123 this->right = r;
00124 this->bottom = b;
00125 }
00126
00127 CoordinateType Width() const
00128 { return AbsoluteFunction::Absolute_Val(this->right - this->left);}
00129 CoordinateType Height() const
00130 { return AbsoluteFunction::Absolute_Val(this->top - this->bottom);}
00131
00132 AIBoolean IsEmpty() const
00133 { return (this->top == this->bottom && this->right == this->left); }
00134 void SetEmpty()
00135 {this->left = this->top = this->right = this->bottom = 0; }
00136
00137 AIBoolean IsNormalized() const
00138 {return this->left <= this->right && this->top <= this->bottom; }
00139 void Normalize() {
00140 if (this->left > this->right)
00141 {
00142 CoordinateType saveLeft = this->left; this->left = this->right; this->right = saveLeft;
00143 }
00144 if (this->top > this->bottom)
00145 {
00146 CoordinateType saveTop = this->top; this->top = this->bottom; this->bottom = saveTop;
00147 }
00148 }
00149
00150 AIBoolean Contains(const PointType& p) const{
00151 return this->left <= p.h && this->right >= p.h && this->top <= p.v && this->bottom >= p.v; }
00152 AIBoolean Contains(const T& r) const{
00153 return this->left <= r.left && this->right >= r.left && this->top <= r.top && this->bottom >= r.top &&
00154 this->left <= r.right && this->right >= r.right && this->top <= r.bottom && this->bottom >= r.bottom; }
00155
00156 CoordinateType Area() const
00157 {return Width() * Height(); }
00158 PointType Center() const{
00159 PointType center;
00160 center.h = (this->left + this->right) / 2;
00161 center.v = (this->top + this->bottom) / 2;
00162 return center;
00163 }
00164 AIBoolean Overlaps(const T& r) const{
00165 return this->right >= r.left && this->left <= r.right &&
00166 this->bottom >= r.top && this->top <= r.bottom;}
00167
00168 IAIRectImpl& operator ++ () {
00169 this->operator += (1); return *this; }
00170 IAIRectImpl& operator -- () {
00171 this->operator -= (1); return *this; }
00172 IAIRectImpl& operator += (CoordinateType n) {
00173 this->left -= n; this->top -= n; this->right += n; this->bottom += n; return *this; }
00174 IAIRectImpl& operator -= (CoordinateType n) {
00175 this->operator += (-n); return *this; }
00176 IAIRectImpl& operator += (const PointType& p) {
00177 this->left += p.h; this->top += p.v; this->right += p.h; this->bottom += p.v; return *this; }
00178 IAIRectImpl& operator -= (PointType& p) {
00179 this->left -= p.h; this->top -= p.v; this->right -= p.h; this->bottom -= p.v; return *this; }
00180
00181 IAIRectImpl& operator = (const PointType& p) {
00182 this->left = this->right = p.h; this->top = this->bottom = p.v;
00183 return *this; }
00184 void Inset(CoordinateType h, CoordinateType v){
00185 this->left += h; this->top += v;
00186 this->right -= h; this->bottom -= v; }
00187 void Inflate(CoordinateType h, CoordinateType v) {
00188 this->left -= h; this->top -= v;
00189 this->right += h; this->bottom += v; }
00190 void Offset(CoordinateType h, CoordinateType v){
00191 this->left += h; this->top += v;
00192 this->right += h; this->bottom += v; }
00193 void Union(const PointType& a) {
00194 this->left = ai::Min(this->left, a.h);
00195 this->top = ai::Min(this->top, a.v);
00196 this->right = ai::Max(this->right, a.h);
00197 this->bottom = ai::Max(this->bottom, a.v);
00198 }
00199 void Union(const T& a){
00200 this->left = ai::Min(a.left, this->left);
00201 this->top = ai::Min(a.top, this->top);
00202 this->right = ai:: Max(a.right, this->right);
00203 this->bottom = ai::Max( a.bottom, this->bottom);}
00204 void Union(const T& a, const T& b) {
00205 this->left = ai::Min(a.left, b.left);
00206 this->top = ai::Min(a.top, b.top);
00207 this->right = ai::Max(a.right, b.right);
00208 this->bottom = ai::Max(a.bottom, b.bottom); }
00209 void Intersect(const T& a) {
00210 this->left = ai::Max(this->left, a.left);
00211 this->top = ai::Max(this->top, a.top);
00212 this->right = ai::Min(this->right, a.right);
00213 this->bottom = ai::Min(this->bottom, a.bottom);
00214
00215 if (!Overlaps(a))
00216 SetEmpty();
00217 }
00218 void Intersect(const T& a, const T& b) {
00219 this->left = ai::Max(a.left, b.left);
00220 this->top = ai::Max(a.top, b.top);
00221 this->right = ai::Min(a.right, b.right);
00222 this->bottom = ai::Min(a.bottom, b.bottom);
00223
00224 if (!Overlaps(a))
00225 SetEmpty();
00226 }
00227
00228 void Center(const T& centerRect) {
00229 Offset(centerRect.left + ((centerRect.right - centerRect.left) - Width()) / 2,
00230 centerRect.top + ((centerRect.bottom - centerRect.top) - Height()) / 2);
00231 }
00232
00233 AIBoolean operator == (const T& a) const
00234 {
00235 return a.left == this->left &&
00236 a.top == this->top &&
00237 a.right == this->right &&
00238 a.bottom == this->bottom;
00239 }
00240 AIBoolean operator != (const T& a) const
00241 {return !(*this == a);}
00242 };
00243
00244 typedef IAIRectImpl<AIRealRect> IAIRealRect;
00245 typedef IAIRectImpl<AIRect> IAIRect;
00246
00247 #endif // __IAIRect__