00001
00011 #ifndef __AARECTANGLE_H__
00012 #define __AARECTANGLE_H__
00013
00014 #include <iostream>
00015 #include <algorithm>
00016
00017 #include "genericalgs.h"
00018
00020 namespace Boundary {
00021
00022 using std::min;
00023 using std::max;
00024
00025
00029 template<class T=int>
00030 struct TwoOrderedPoints {
00032 T xl,yl,xh,yh;
00033
00034 inline TwoOrderedPoints(const T& xlow=0, const T& ylow=0,
00035 const T& xhigh=0,const T& yhigh=0)
00036 : xl(xlow), yl(ylow), xh(xhigh), yh(yhigh) { }
00037 };
00038
00039
00040
00050 template<class T=int,class Boolean=bool,class Float=double>
00051 struct AARectangle {
00052 private:
00053 typedef AARectangle<T,Boolean,Float> self;
00054 typedef TwoOrderedPoints<T> Points;
00055
00056 public:
00057 typedef T value_type;
00058
00060 inline AARectangle(const T& xlow=0, const T& ylow=0,
00061 const T& xhigh=0,const T& yhigh=0)
00062 : p(xlow,ylow,xhigh,yhigh) { }
00063
00066 inline Boolean inside(T x, T y) const
00067 { return (x>=p.xl && y>=p.yl && x<=p.xh && y<=p.yh); }
00068
00072 inline Boolean upperexclusive_inside(T x, T y) const
00073 { return (x>=p.xl && y>=p.yl && x<p.xh && y<p.yh); }
00074
00082 inline self& operator+=( const self& o ) {
00083 if (empty()) { p=o.p; }
00084 else { p.xl=min(p.xl,o.p.xl); p.yl=min(p.yl,o.p.yl); p.xh=max(p.xh,o.p.xh); p.yh=max(p.yh,o.p.yh); }
00085 return *this;
00086 }
00087
00089 inline self& scale( T xscale, T yscale ) {
00090 p.xl=p.xl*xscale; p.yl=p.yl*yscale; p.xh=p.xh*xscale; p.yh=p.yh*yscale;
00091 return *this;
00092 }
00093
00097 self& rotate( Float theta ) {
00098 const Float cosmt = cos(-theta);
00099 const Float sinmt = sin(-theta);
00100
00101 const T xlc = T(p.xl*cosmt); const T xls = T(p.xl*sinmt);
00102 const T xhc = T(p.xh*cosmt); const T xhs = T(p.xh*sinmt);
00103 const T ylc = T(p.yl*cosmt); const T yls = T(p.yl*sinmt);
00104 const T yhc = T(p.yh*cosmt); const T yhs = T(p.yh*sinmt);
00105
00106 p.xl = min(min(min(xlc-yls,xlc-yhs),xhc-yls),xhc-yhs);
00107 p.xh = max(max(max(xlc-yls,xlc-yhs),xhc-yls),xhc-yhs);
00108
00109 p.yl = min(min(min(xls+ylc,xls+yhc),xhs+ylc),xhs+yhc);
00110 p.yh = max(max(max(xls+ylc,xls+yhc),xhs+ylc),xhs+yhc);
00111
00112 return *this;
00113 }
00114
00116 inline self& translate( T xoffset, T yoffset ) {
00117 p.xl+=xoffset; p.yl+=yoffset; p.xh+=xoffset; p.yh+=yoffset;
00118 return *this;
00119 }
00120
00122 inline self& set(T xlow, T ylow, T xhigh, T yhigh ) {
00123 p.xl=xlow; p.yl=ylow; p.xh=xhigh; p.yh=yhigh;
00124 return *this;
00125 }
00126
00128 inline self& set (const Points& o) { p=o; }
00129
00130
00131 inline self intersection(const self& o) {
00132 return self(Generic::crop(o.p.xl,o.p.xh,p.xl),
00133 Generic::crop(o.p.yl,o.p.yh,p.yl),
00134 Generic::crop(o.p.xl,o.p.xh,p.xh),
00135 Generic::crop(o.p.yl,o.p.yh,p.yh));
00136 }
00137
00139 inline T height() const { return (std::abs(p.yh-p.yl)); }
00140
00142 inline T width() const { return (std::abs(p.xh-p.xl)); }
00143
00145 inline Points corners() const { return p; }
00146
00150 inline Boolean empty() const { return (height()==0 || width()==0); }
00151
00153 inline std::ostream& put(std::ostream &s) const
00154 { return (s << "((" << p.xl << "," << p.yl << ") (" << p.xh << "," << p.yh << "))"); }
00155
00156 private:
00157 Points p;
00158 };
00159
00160
00161
00165 template<class T=int,class Boolean=bool,class Float=double>
00166 class AAArbitraryRectangle {
00167 private:
00168 typedef AAArbitraryRectangle<T,Boolean,Float> self;
00169 typedef AARectangle<T,Boolean,Float> PlainRect;
00170 typedef TwoOrderedPoints<T> Points;
00171
00172 public:
00173 typedef T value_type;
00174
00176 inline AAArbitraryRectangle() : infinite(true) { }
00177
00179 inline AAArbitraryRectangle(T xlow, T ylow, T xhigh, T yhigh )
00180 : infinite(false), rect(xlow,ylow,xhigh,yhigh) { }
00181
00182 inline Boolean isinfinite() const { return infinite; }
00183
00184 inline Boolean inside(T x, T y) const
00185 { return (infinite || rect.inside(x,y)); }
00186
00187 inline Boolean upperexclusive_inside(T x, T y) const
00188 { return (infinite || rect.upperexclusive_inside(x,y)); }
00189
00191 inline self& set() { infinite=true; return *this; }
00192
00193 inline self& set(T xlow, T ylow, T xhigh, T yhigh)
00194 { infinite=false; rect.set(xlow,ylow,xhigh,yhigh); return *this; }
00195
00203 inline self& operator+=( const self& b ) {
00204 if (infinite || b.infinite) infinite=true;
00205 else rect+=b.rect;
00206 return *this;
00207 }
00208
00210 inline self& scale( T xscale, T yscale )
00211 { if (!infinite) rect.scale(xscale,yscale); return *this; }
00212
00215 inline self& rotate( Float theta )
00216 { if (!infinite) rect.rotate(theta); return *this; }
00217
00219 inline self& translate( T xoffset, T yoffset )
00220 { if (!infinite) rect.translate(xoffset,yoffset); return *this; }
00221
00223 inline std::ostream& put(std::ostream &s) const
00224 { return (infinite? s << "(Infinite)" : rect.put(s)); }
00225
00226
00227 inline self& intersection(const self& o) {
00228 return (o.isinfinite()? *this :
00229 (isinfinite()? o :
00230 self(rect.intersection(o.rect))));
00231 }
00232
00234 inline T height() const { return (infinite? 0 : rect.height()); }
00235
00237 inline T width() const { return (infinite? 0 : rect.width()); }
00238
00241 inline PlainRect aarectangle() const { return (infinite? PlainRect() : rect); }
00242
00244 inline Points corners() const { return rect.corners(); }
00245
00249 inline Boolean empty() const
00250 { return (!infinite && rect.empty()); }
00251
00252 private:
00253 Boolean infinite;
00254 PlainRect rect;
00255 };
00256
00257
00258 }
00259 #endif