# BoundingBox.h

Go to the documentation of this file.
```00001 #ifndef INCLUDED_BoundingBox_H
00002 #define INCLUDED_BoundingBox_H
00003
00004 #include "fmatCore.h"
00005 #include <limits>
00006 #include <cmath>
00007 #include <cstdlib>
00008
00009 //! Bounding box of a shape; used for coordinate calculations
00010 template<size_t N, typename T=fmat::fmatReal>
00011 class BoundingBox {
00012 public:
00013   static const BoundingBox ALL_INCLUSIVE; //!< a bounding box initialized to contain everything: (-∞,∞)
00014   static const BoundingBox ALL_EXCLUSIVE; //!< a bounding box initialized to exclude everything: (∞,-∞) — this is also default construction
00015
00016   fmat::Column<N,T> min; //!< minimum corner
00017   fmat::Column<N,T> max; //!< maximum corner
00018
00019   //! Constructor, defaults to empty bounding box (aka ALL_EXCLUSIVE)
00020   /*! Using inverted infinities, so no point should collide,
00021       and any expansion will collapse to the expansion. */
00022   BoundingBox() :
00023     min( std::numeric_limits<T>::infinity()),
00024     max(-std::numeric_limits<T>::infinity()) {}
00025
00026   //! Constructor for 2D boxes
00027   BoundingBox(T xmin, T ymin, T xmax, T ymax) :
00028     min(), max() { min[0]=xmin; min[1]=ymin; max[0]=xmax; max[1]=ymax; }
00029
00030   //! Conversion between types (same dimensionality)
00031   template<typename R> BoundingBox(const BoundingBox<N,R>& bb) : min(bb.min), max(bb.max) {}
00032
00033   //! Conversion between type/dimensions.
00034   /*! If @a inclusive is set and this is an 'upcast' (D < N), extra dimensions will be set to all-inclusive (-∞,∞).
00035    *  Otherwise, extra dimensions will be set to all-exclusive (∞,-∞) and you would need to provide
00036    *  additional expansion in order to form a positive volume. */
00037   template<size_t D, typename R> explicit BoundingBox(const BoundingBox<D,R>& bb, bool inclusive=true) :
00038     min(inclusive?-std::numeric_limits<T>::infinity():std::numeric_limits<T>::infinity()),
00039     max(inclusive?std::numeric_limits<T>::infinity():-std::numeric_limits<T>::infinity())
00040   {
00041     const size_t MIN=(D<N)?D:N;
00042     (fmat::SubVector<MIN,T>)min = fmat::SubVector<MIN,const R>(bb.min);
00043     (fmat::SubVector<MIN,T>)max = fmat::SubVector<MIN,const R>(bb.max);
00044   }
00045
00046   //! Constructor for single-point box (note collision requires non-zero area)
00047   template<class P> explicit BoundingBox(const P& p) : min(p), max(p) {}
00048
00049   //! Constructor, specify min/max directly (you are responsible to ensure min << max)
00050   template<class P> explicit BoundingBox(const P& _min, const P& _max) : min(_min), max(_max) {}
00051
00052   //! Returns true if box has zero or negative area
00053   bool empty() const { return !(min << max); }
00054
00055   //! Sets min and max to default values (negative infinite area)
00056   void clear() { max = -(min = std::numeric_limits<T>::infinity()); }
00057
00058   //! Return the width of dimenion @a x (Cowabunga Dude!)
00059   T getDimension(size_t x) const { return max[x]-min[x]; }
00060
00061   //! Return the width of each dimension
00062   fmat::Column<N,T> getDimensions() const { return max-min; }
00063
00064   //! Returns the center of the bounding box
00065   fmat::Column<N,T> getCenter() const { return (min+max)/2; }
00066
00067   //! Returns a random point within the bounding box (including edges)
00068   fmat::Column<N,T> getRandom() const {
00069     fmat::Column<N,T> ans = fmat::fmat_internal::NoInit();
00070     for(size_t i=0; i<N; ++i) {
00071       // Aperios doesn't provide a random(), only rand()...
00072       // For testing consistency, Aibo target models always use rand(), regardless of local/aperios platform.
00073 #if defined(TGT_ERS210) || defined(TGT_ERS220) || defined(TGT_ERS2xx) || defined(TGT_ERS7) || defined(PLATFORM_APERIOS)
00074       ans[i] = rand() / (T)RAND_MAX * (max[i]-min[i]) + min[i];
00075 #else
00076       ans[i] = random() / (T)((1U<<31)-1) * (max[i]-min[i]) + min[i];
00077 #endif
00078     }
00079     return ans;
00080   }
00081
00082   //! Expand the bounding box to include @a p
00083   /*! This picks up columns of the correct size */
00084   template<class R> void expand(const fmat::Column<N,R>& p) { min.minimize(p); max.maximize(p); }
00085
00086   //! Expand the bounding box to include @a p
00087   /*! This picks up subvectors of the correct size */
00088   template<class R> void expand(const fmat::SubVector<N,R>& p) { min.minimize(p); max.maximize(p); }
00089
00090   //! Expand the bounding box to include @a p
00091   /*! This version picks up extended-dimenion points, arrays, and column subclasses, converting to a SubVector intermediary.
00092    *  Allows implicit truncation of 3D to 2D, since this is pretty commonly used in DualCoding. */
00093   template<class P> void expand(const P& p) {
00094     fmat::SubVector<N,const T> pp(p);
00095     min.minimize(pp); max.maximize(pp);
00096   }
00097
00098   //! Expand the bounding box to include @a bb
00099   void expand(const BoundingBox& bb) {
00100     min.minimize(bb.min);
00101     max.maximize(bb.max);
00102   }
00103
00104   //! Applies the specified rotation about the bounding box center, then resets to the axis-aligned boundaries of the rotated bounding box
00105   /*! This does not handle bounding boxes with infinite bounds. */
00106   void rotate(fmat::Matrix<N,N> r) { // pass-by-copy because we modify it during execution
00107     fmat::Column<N,T> c = getCenter();
00108 #if defined(DEBUG) && !defined(PLATFORM_APERIOS)
00109     for(size_t i=0; i<N; ++i) {
00110       if(!std::isfinite(c[i])) {
00111         std::cerr << "BoundingBox::rotate() applied to infinite boundaries" << std::endl;
00112         break;
00113       }
00114     }
00115 #endif
00116     r.abs();
00117     fmat::Column<N,T> x = r*(max - c);
00118     max = c + x;
00119     min = c - x;
00120   }
00121
00122   //! Translates the bounding box, moving the min and max bounds
00123   void translate(const fmat::Column<N>& x) {
00124     min+=x;
00125     max+=x;
00126   }
00127
00128   void transform(const fmat::Matrix<N,N>& r, const fmat::Column<N>& x) {
00129     rotate(r);
00130     recenter(r*getCenter() + x);
00131   }
00132
00133   //! Translates the bounding box, moving the min and max bounds such that the center is placed at @a c
00134   void recenter(const fmat::Column<N>& c) {
00135     fmat::Column<N,T> d = getDimensions()/2;
00136     min = c - d;
00137     max = c + d;
00138   }
00139
00140   //! Return true if this box includes p (note edge coincidence does not count)
00141   template<class P> bool collides(const P& p) const {
00142     return ( min << p ) && ( p << max );
00143   }
00144
00145   //! Return true if this box intersects p (note edge coincidence does not count)
00146   bool collides(const BoundingBox& bb) const {
00147     for(size_t i=N; i>0; ) {
00148       --i;
00149       // if we find an axis which does not overlap, then bb do not overlap
00150       if( (bb.max[i]<=min[i]) || (max[i]<=bb.min[i]) )
00151         return false;
00152     }
00153     // if all axes' components overlap, then bb overlap
00154     return true;
00155   }
00156
00157   //! Returns a corner of the box as determined by which bits are set
00158   /*! The ith bit corresponds to the ith axis,
00159     0 returns lower bound, and 1 returns upper bound */
00160   fmat::Column<N,T> getCorner(size_t x) const {
00161     fmat::Column<N,T> ans=min;
00162     for(size_t i=N; i>0; ) {
00163       --i;
00164       if( (x>>i)&1 )
00165         ans[i]=max[i];
00166     }
00167     return ans;
00168   }
00169
00170   //! For display/serialization
00171   friend std::ostream& operator<<(std::ostream& out, const BoundingBox& bb) {
00172     out << "BoundingBox(";
00173     size_t i=0;
00174     do {
00175       out << bb.min[i] << ":" << bb.max[i];
00176     } while(++i < N && (out << ", "));
00177     out << ")";
00178     return out;
00179   }
00180
00181   // equality test
00182   bool operator==(const BoundingBox& bb) const { return min==bb.min && max==bb.max; }
00183
00184   // inequality test
00185   bool operator!=(const BoundingBox& bb) const { return min!=bb.min || max!=bb.max; }
00186 };
00187
00188 template<size_t N, typename T> const BoundingBox<N,T>
00189 BoundingBox<N,T>::ALL_INCLUSIVE(-std::numeric_limits<T>::infinity(),std::numeric_limits<T>::infinity());
00190
00191 template<size_t N, typename T> const BoundingBox<N,T>
00192 BoundingBox<N,T>::ALL_EXCLUSIVE(std::numeric_limits<T>::infinity(),-std::numeric_limits<T>::infinity());
00193
00194 extern template class BoundingBox<2>;
00195 extern template class BoundingBox<3>;
00196
00197 typedef BoundingBox<2> BoundingBox2D;
00198 typedef BoundingBox<3> BoundingBox3D;
00199
00200 #endif
```

 Tekkotsu v5.1CVS Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3