Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

boundingbox.h

Go to the documentation of this file.
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       Type double is used for the temporary to avoid truncation in
00109       case T is an integer.  But unfortunately this will cause
00110       truncation in the (probably unlikely) case that T should be
00111       something more powerful than a double for which sin and cos are
00112       defined, e.g. complex.
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     /* These could be cached */
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     /* This routine should be straightforward to implement, since it would
00196        just need to rotate each corner about the center.   However, it would
00197        be tedious to do, and the inside() routine would need to be modified
00198        to match.  So it is left undone since this routine is not
00199        currently needed.
00200     */
00201     abort();
00202     return *this;
00203   }
00204 };
00205 
00206 #endif /* __BOUNDINGBOX_H__ */

Generated at Mon Aug 21 00:30:54 2000 for RF-LISSOM by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000