BoundingBox.h

Go to the documentation of this file.
00001 #ifndef BoundingBox_HEADER
00002 #define BoundingBox_HEADER
00003 
00004 #include <algorithm>
00005 #include <utilities/identity.h>
00006 
00007 #include "Point.h"
00008 #include "ProjectionPlane.h"
00009 
00010 namespace Geometry {
00011 
00012 /***************************************************************************
00013  * Compute an orthogonal bounding box around a set of points.
00014  ***************************************************************************/
00015 template <unsigned d>
00016 struct BoundingBox {
00017   typedef Geometry::Point<d> Point;
00018   static const unsigned dimension = d;
00019 
00020   Point mincorner;
00021   double extent;
00022 
00023   BoundingBox(): mincorner(0.0), extent(0.0) { }
00024 
00025   BoundingBox(Point p, double e)
00026     : mincorner(p), extent(e) { }
00027 
00028   /* Compute the bounding box of the points indicated by the range. */
00029   template <class iterator>
00030   BoundingBox(iterator begin, iterator end) {
00031     init(begin, end, hudson::form_identity(*begin));
00032   }
00033 
00034   /* Compute the bounding box of the points indicated by the range,
00035      projected to the given plane. */
00036   template <class iterator, unsigned ambient>
00037   BoundingBox(iterator begin, iterator end,
00038               const ProjectionPlane<ambient, d>& plane) {
00039     typedef ProjectionPlane<ambient, d> ProjectionPlane;
00040     init(begin, end, std::bind1st(std::mem_fun(&ProjectionPlane::project1), &plane));
00041   }
00042 
00043   /* Compute the bounding box of the points indicated by the range,
00044      transformed by the given operator. */
00045   template <class iterator, class xform>
00046   BoundingBox(iterator begin, iterator end, const xform& x) {
00047     init(begin, end, x);
00048   }
00049 
00050   /* Scale the box to have the same center but have
00051    * a buffer around its sides.  For example, a buffer
00052    * of 1.0 yields a box three times bigger. */
00053   BoundingBox scale(double buffer) const {
00054     BoundingBox bigbox;
00055     bigbox.mincorner = mincorner -
00056       (Point(1.0) * buffer * extent);
00057     bigbox.extent = extent * (1.0 + 2.0 * buffer);
00058     return bigbox;
00059   }
00060 
00061   bool bitwiseEqual(const BoundingBox& other) const {
00062     return extent == other.extent
00063       && mincorner.bitwiseEqual(other.mincorner);
00064   }
00065 
00066   /* Open box */
00067   bool inBox(const Point& p) const {
00068     for(size_t i = 0; i < d; ++i) {
00069       if (p[i] < mincorner[i] || p[i] > mincorner[i] + extent) {
00070         return false;
00071       }
00072     }
00073     return true;
00074   }
00075 
00076   bool inClosedBox(const Point& p) const {
00077     for(size_t i = 0; i < d; ++i) {
00078       if (p[i] <= mincorner[i] || p[i] >= mincorner[i] + extent) {
00079         return false;
00080       }
00081     }
00082     return true;
00083   }
00084 
00085   std::string toString() const {
00086     char buffer[4096];
00087     sprintf(buffer, ", sidelength = %g", extent);
00088     return mincorner.toString() + buffer;
00089   }
00090 
00091   private:
00092   template <class iterator, class xform>
00093   void init(iterator begin, iterator end, const xform& x) {
00094     assert(begin != end);
00095     Point mincoords, maxcoords; // uninitialized
00096     iterator it = begin;
00097     mincoords = maxcoords = x(*it); // don't init to zero!
00098     Point sum(x(*begin));
00099     size_t n = 1;
00100     for(++it ; it != end; ++it) {
00101       Point p = x(*it);
00102       n++;
00103       for(unsigned i = 0; i < d; i++) {
00104         mincoords[i] = std::min(mincoords[i], p[i]);
00105         maxcoords[i] = std::max(maxcoords[i], p[i]);
00106       }
00107     }
00108     extent = 0.0;
00109     for (unsigned i = 0; i < d; i++) {
00110       extent = std::max(maxcoords[i] - mincoords[i], extent);
00111     }
00112     Point center = (maxcoords + mincoords) * 0.5;
00113     mincorner = center - Point(1) * (extent / 2.0);
00114     /* in case of numerical error in the previous */
00115     if ( (mincoords - mincorner).norm1() < 0.0 ) {
00116       mincorner = mincoords;
00117     }
00118   }
00119 };
00120 
00121 }
00122 
00123 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6