00001
00010 #ifndef __BOUNDINGBOX_H__
00011 #define __BOUNDINGBOX_H__
00012
00013 #include <iostream>
00014
00015 using std::min;
00016 using std::max;
00017
00018
00020 template<class T=double>
00021 class BoundingBox {
00022 public:
00024 virtual bool inside(T x, T y) const =0;
00025
00027 virtual BoundingBox<T>& scale(T xscale, T yscale) =0;
00028
00030 virtual BoundingBox<T>& rotate(T angle) =0;
00031
00033 virtual BoundingBox<T>& translate(T xoffset, T yoffset) =0;
00034
00039 virtual ostream& put(ostream &s) const { return s; };
00040 };
00041
00042
00043
00045 template <class T>
00046 ostream& operator<<(ostream &s, const BoundingBox<T>& b) { return b.put(s); }
00047
00048
00049
00051 template<class T=double>
00052 class AARBoundingBox : public BoundingBox<T> {
00053 public:
00055 AARBoundingBox() : infinite(true) { }
00056
00058 AARBoundingBox(T xlow, T ylow, T xhigh, T yhigh )
00059 : infinite(false), xl(xlow), yl(ylow), xh(xhigh), yh(yhigh) { }
00060
00063 AARBoundingBox(T centerx, T centery, T radius )
00064 : infinite(false), xl(centerx-radius), yl(centery-radius), xh(centerx+radius), yh(centery+radius) { }
00065
00067 virtual bool inside(T x, T y) const
00068 { return (infinite || (x>=xl && y>=yl && x<=xh && y<=yh)); }
00069
00071 virtual AARBoundingBox<T>& set() { infinite=true; return *this; }
00072
00074 virtual AARBoundingBox<T>& set(T xlow, T ylow, T xhigh, T yhigh ) {
00075 infinite=false;
00076 xl=xlow; yl=ylow; xh=xhigh; yh=yhigh;
00077 return *this;
00078 }
00079
00087 virtual AARBoundingBox<T>& operator+=( const AARBoundingBox<T>& b ) {
00088 if (infinite || b.infinite) infinite=true;
00089 else if (empty()) { xl=b.xl; yl=b.yl; xh=b.xh; yh=b.yh; }
00090 else { xl=min(xl,b.xl); yl=min(yl,b.yl); xh=max(xh,b.xh); yh=max(yh,b.yh); }
00091
00092 return *this;
00093 }
00094
00096 virtual BoundingBox<T>& scale( T xscale, T yscale ) {
00097 if (!infinite)
00098 { xl=xl*xscale; yl=yl*yscale; xh=xh*xscale; yh=yh*yscale; }
00099 return *this;
00100 }
00101
00104 virtual BoundingBox<T>& rotate( T theta ) {
00105 if (infinite) return *this;
00106
00107 00108 00109 00110 00111 00112 00113
00114 const double cosmt = cos(-theta); const double sinmt = sin(-theta);
00115 const T xlc = xl*cosmt; const T xls = xl*sinmt;
00116 const T xhc = xh*cosmt; const T xhs = xh*sinmt;
00117 const T ylc = yl*cosmt; const T yls = yl*sinmt;
00118 const T yhc = yh*cosmt; const T yhs = yh*sinmt;
00119
00120 xl = min(min(min(xlc-yls,xlc-yhs),xhc-yls),xhc-yhs);
00121 xh = max(max(max(xlc-yls,xlc-yhs),xhc-yls),xhc-yhs);
00122
00123 yl = min(min(min(xls+ylc,xls+yhc),xhs+ylc),xhs+yhc);
00124 yh = max(max(max(xls+ylc,xls+yhc),xhs+ylc),xhs+yhc);
00125
00126 return *this;
00127 }
00128
00130 virtual BoundingBox<T>& translate( T xoffset, T yoffset ) {
00131 if (!infinite)
00132 { xl=xl+xoffset; yl=yl+yoffset; xh=xh+xoffset; yh=yh+yoffset; }
00133 return *this;
00134 }
00135
00136 virtual ostream& put(ostream &s) const
00137 { return (infinite? s << "(Infinite)"
00138 : s << "((" << xl << "," << yl << ") (" << xh << "," << yh << "))"); }
00139
00140 protected:
00141 bool infinite;
00142 T xl,yl,xh,yh;
00143
00145 virtual bool empty() const
00146 { return (!infinite && xh-xl==0 && yh-yl==0 ); }
00147 };
00148
00149
00150
00158 template<class T=double>
00159 class BoundingEllipse : public AARBoundingBox<T> {
00160 public:
00162 BoundingEllipse() : AARBoundingBox<T>() { }
00163
00165 BoundingEllipse(T centerx, T centery, T radius )
00166 : AARBoundingBox<T>(centerx-radius,centery-radius,centerx+radius,centery+radius) { }
00167
00169 BoundingEllipse(T centerx, T centery, T radiusx, T radiusy )
00170 : AARBoundingBox<T>(centerx-radiusx,centery-radiusy,centerx+radiusx,centery+radiusy) { }
00171
00173 virtual bool inside(T x, T y) const {
00174 if (infinite) return true;
00175
00176
00177 const double radiusx = (xh-xl)/2.0;
00178 const double radiusy = (yh-yl)/2.0;
00179 const double div_radiusx_sq = 1/(radiusx*radiusx);
00180 const double div_radiusy_sq = 1/(radiusy*radiusy);
00181 const T centerx = xl+T(radiusx);
00182 const T centery = yl+T(radiusy);
00183
00184 const T xdistance = x-centerx;
00185 const T ydistance = y-centery;
00186 const T xdistance_sq = xdistance*xdistance;
00187 const T ydistance_sq = ydistance*ydistance;
00188
00189 return (xdistance_sq*div_radiusx_sq + ydistance_sq*div_radiusy_sq < 1);
00190 }
00191
00192
00194 virtual BoundingBox<T>& rotate( T theta ) {
00195 00196 00197 00198 00199 00200
00201 abort();
00202 return *this;
00203 }
00204 };
00205
00206 #endif