00001
00012 #ifndef __BOUNDINGBOX_H__
00013 #define __BOUNDINGBOX_H__
00014
00015 #include <iostream>
00016 #include "aarectangle.h"
00017 #include "genericalgs.h"
00018
00019
00020 namespace Boundary {
00021
00022
00028 template<class T=double, class Boolean=bool, class Float=double>
00029 class BoundingBox {
00031 typedef BoundingBox<T,Boolean,Float> self;
00032 typedef BoundingBox<T,Boolean,Float> base;
00033
00034 public:
00035 typedef AARectangle<T,Boolean,Float> Rectangle;
00036 typedef T value_type;
00037
00039 virtual Boolean inside(T x, T y) const =0;
00040
00042 virtual base& scale(T xscale, T yscale) =0;
00043
00045 virtual base& rotate(Float angle) =0;
00046
00048 virtual base& translate(T xoffset, T yoffset) =0;
00049
00052 virtual Rectangle aarectangle() const =0;
00053
00055 virtual base* clone() const=0;
00056
00062 virtual std::ostream& put(std::ostream &s) const { return s; };
00063 };
00064
00065
00066
00068 template<class T,class Boolean,class Float>
00069 std::ostream& operator<<(std::ostream &s, const BoundingBox<T,Boolean,Float>& b) { return b.put(s); }
00070
00071
00072
00079 template<class T=int,class Boolean=bool,class Float=double,
00080 class BoxType=AAArbitraryRectangle<T,Boolean,Float> >
00081 class AARBoundingBox : public BoundingBox<T,Boolean,Float> {
00082 private:
00083 typedef AARBoundingBox<T,Boolean,Float,BoxType> self;
00084 typedef BoundingBox<T,Boolean,Float> base;
00085
00086 public:
00088 AARBoundingBox() { }
00089
00091 AARBoundingBox(T xlow, T ylow, T xhigh, T yhigh )
00092 : box(xlow,ylow,xhigh,yhigh) { }
00093
00096 AARBoundingBox(T centerx, T centery, T radius )
00097 : box(centerx-radius,centery-radius,centerx+radius,centery+radius) { }
00098
00099 virtual Boolean inside(T x, T y) const { return box.inside(x,y); }
00100
00102 virtual self& set() { box.set(); return *this; }
00103
00105 virtual self& set(T xlow, T ylow, T xhigh, T yhigh)
00106 { box=BoxType(xlow,ylow,xhigh,yhigh); return *this; }
00107
00109 virtual self& operator+=( const self& b )
00110 { box += b.box; return *this; }
00111
00112 virtual base& scale( T xscale, T yscale )
00113 { box.scale(xscale,yscale); return *this; }
00114
00117 virtual base& rotate( Float theta ) { box.rotate(theta); return *this; }
00118
00119 virtual base& translate( T xoffset, T yoffset )
00120 { box.translate(xoffset,yoffset); return *this; }
00121
00122 virtual typename base::Rectangle aarectangle() const
00123 { return (box.isinfinite()? typename base::Rectangle() : box.aarectangle()); }
00124
00125 virtual base* clone() const { return new self(*this); };
00126
00127 virtual std::ostream& put(std::ostream &s) const
00128 { return box.put(s); }
00129
00132 virtual Boolean empty() const
00133 { return box.empty(); }
00134
00135 protected:
00136 BoxType box;
00137 };
00138
00139
00140
00156 template<class T=int,class Boolean=bool,class Float=double,
00157 class BoxType=AAArbitraryRectangle<T,Boolean,Float> >
00158 class BoundingEllipse : public AARBoundingBox<T,Boolean,Float,BoxType> {
00159 typedef BoundingBox<T,Boolean,Float> base;
00160 typedef BoundingEllipse<T,Boolean,Float,BoxType> self;
00161 typedef AARBoundingBox<T,Boolean,Float> aarbase;
00162
00163 public:
00165 BoundingEllipse() : aarbase(), trimx(0), trimy(0) { }
00166
00168 BoundingEllipse(T centerx, T centery, T radius, Float trim=0 )
00169 : aarbase(centerx-radius,centery-radius,centerx+radius,centery+radius),
00170 trimx(trim), trimy(trim) { }
00171
00173 BoundingEllipse(T centerx, T centery, T radiusx, T radiusy, Float trimx_i=0, Float trimy_i=0)
00174 : aarbase(centerx-radiusx,centery-radiusy,centerx+radiusx,centery+radiusy),
00175 trimx(trimx_i), trimy(trimy_i) { }
00176
00179 virtual Boolean inside(T x, T y) const {
00180 if (box.isinfinite()) return true;
00181
00182
00183 const Float radiusx = (box.width())/2.0+trimx;
00184 const Float radiusy = (box.height())/2.0+trimy;
00185 const Float div_radiusx_sq = 1/(radiusx*radiusx);
00186 const Float div_radiusy_sq = 1/(radiusy*radiusy);
00187 const T centerx = box.corners().xl+T(radiusx);
00188 const T centery = box.corners().yl+T(radiusy);
00189
00190 const T xdistance = x-centerx;
00191 const T ydistance = y-centery;
00192 const T xdistance_sq = xdistance*xdistance;
00193 const T ydistance_sq = ydistance*ydistance;
00194
00195 return (xdistance_sq*div_radiusx_sq + ydistance_sq*div_radiusy_sq < 1);
00196 }
00197
00198
00200 virtual base& rotate( Float theta ) {
00201 (void)theta;
00202
00203
00204
00205
00206
00207
00208 abort();
00209 return *this;
00210 }
00211
00212 virtual base* clone() const { return new self(*this); }
00213
00214 private:
00215 Float trimx,trimy;
00216 };
00217
00218
00221 template<class T=int,class Boolean=bool,class Float=double,
00222 class BBA=BoundingEllipse<T,Boolean,Float>,
00223 class BBB=AARBoundingBox<T,Boolean,Float> >
00224 class Intersection : public BoundingBox<T,Boolean,Float> {
00225 typedef BoundingBox<T,Boolean,Float> base;
00226 typedef Intersection<T,Boolean,Float,BBA,BBB> self;
00227 typedef AARBoundingBox<T,Boolean,Float> aarbase;
00228
00229 public:
00231 Intersection(const BBA& bb_a=BBA(), const BBB& bb_b=BBB())
00232 : a(bb_a), b(bb_b) { }
00233
00236 virtual Boolean inside(T x, T y) const
00237 { return (a.inside(x,y) && b.inside(x,y)); }
00238
00240 virtual base& scale(T xscale, T yscale)
00241 { a.scale(xscale,yscale); b.scale(xscale,yscale); return *this; }
00242
00244 virtual base& rotate(Float angle)
00245 { a.rotate(angle); b.rotate(angle); return *this; }
00246
00248 virtual base& translate(T xoffset, T yoffset)
00249 { a.translate(xoffset,yoffset); b.translate(xoffset,yoffset); return *this; }
00250
00253 virtual typename base::Rectangle aarectangle() const { return a.aarectangle().intersection(b.aarectangle()); }
00254
00255 virtual base* clone() const { return new self(*this); };
00256
00257 virtual std::ostream& put(std::ostream &s) const
00258 { s<<"("; a.put(s); s<<" && "; b.put(s); s<<")"; return s; };
00259
00260 private:
00261 BBA a;
00262 BBB b;
00263 };
00264
00265
00266
00268 template<class T=int,class Boolean=bool,class Float=double>
00269 class BoundingCircle : public BoundingBox<T,Boolean,Float> {
00270 private:
00271 typedef BoundingCircle<T,Boolean,Float> self;
00272 typedef BoundingBox<T,Boolean,Float> base;
00273
00274 public:
00276 BoundingCircle(): infinite(true) { }
00277
00279 BoundingCircle(T centerx_, T centery_, Float radius_ )
00280 : infinite(false), centerx(centerx_), centery(centery_), radius(radius_)
00281 { freshencache(); }
00282
00283 inline Boolean isinfinite() const { return infinite; }
00284
00285 virtual Boolean inside(T x, T y) const {
00286 if (isinfinite()) return true;
00287
00288 const T xdistance = x-centerx;
00289 const T ydistance = y-centery;
00290 const T xdistance_sq = xdistance*xdistance;
00291 const T ydistance_sq = ydistance*ydistance;
00292
00293 return (xdistance_sq + ydistance_sq <= radius_sq);
00294 }
00295
00297 virtual base& scale( T xscale, T yscale )
00298 { radius*=xscale; (void)yscale; assert(xscale==yscale); freshencache(); return *this; }
00299
00301 virtual base& rotate( Float ) { return *this; }
00302
00303 virtual base& translate( T xoffset, T yoffset )
00304 { centerx+=xoffset; centery+=yoffset; freshencache(); return *this; }
00305
00308 virtual typename base::Rectangle aarectangle() const {
00309 return (isinfinite()?
00310 typename base::Rectangle() :
00311 typename base::Rectangle(T(centerx)-T(radius),T(centery)-T(radius),
00312 T(centerx)+T(radius),T(centery)+T(radius)));
00313 }
00314
00315 virtual base* clone() const { return new self(*this); };
00316
00317 virtual std::ostream& put(std::ostream &s) const
00318 { return (s << "((" << centerx << "," << centery << ") radius " << radius << ")"); }
00319
00320 private:
00321 Boolean infinite;
00322
00323 T centerx;
00324 T centery;
00325 Float radius;
00326
00327
00329 Float radius_sq;
00330 void freshencache() { radius_sq = radius*radius; }
00332 };
00333
00334
00335
00336
00337 }
00338
00339
00340 using namespace Boundary;
00341
00342 #endif