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
00010 template<size_t N, typename T=fmat::fmatReal>
00011 class BoundingBox {
00012 public:
00013 static const BoundingBox ALL_INCLUSIVE;
00014 static const BoundingBox ALL_EXCLUSIVE;
00015
00016 fmat::Column<N,T> min;
00017 fmat::Column<N,T> max;
00018
00019
00020
00021
00022 BoundingBox() :
00023 min( std::numeric_limits<T>::infinity()),
00024 max(-std::numeric_limits<T>::infinity()) {}
00025
00026
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
00031 template<typename R> BoundingBox(const BoundingBox<N,R>& bb) : min(bb.min), max(bb.max) {}
00032
00033
00034
00035
00036
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
00047 template<class P> explicit BoundingBox(const P& p) : min(p), max(p) {}
00048
00049
00050 template<class P> explicit BoundingBox(const P& _min, const P& _max) : min(_min), max(_max) {}
00051
00052
00053 bool empty() const { return !(min << max); }
00054
00055
00056 void clear() { max = -(min = std::numeric_limits<T>::infinity()); }
00057
00058
00059 T getDimension(size_t x) const { return max[x]-min[x]; }
00060
00061
00062 fmat::Column<N,T> getDimensions() const { return max-min; }
00063
00064
00065 fmat::Column<N,T> getCenter() const { return (min+max)/2; }
00066
00067
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
00072
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
00083
00084 template<class R> void expand(const fmat::Column<N,R>& p) { min.minimize(p); max.maximize(p); }
00085
00086
00087
00088 template<class R> void expand(const fmat::SubVector<N,R>& p) { min.minimize(p); max.maximize(p); }
00089
00090
00091
00092
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
00099 void expand(const BoundingBox& bb) {
00100 min.minimize(bb.min);
00101 max.maximize(bb.max);
00102 }
00103
00104
00105
00106 void rotate(fmat::Matrix<N,N> r) {
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
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
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
00141 template<class P> bool collides(const P& p) const {
00142 return ( min << p ) && ( p << max );
00143 }
00144
00145
00146 bool collides(const BoundingBox& bb) const {
00147 for(size_t i=N; i>0; ) {
00148 --i;
00149
00150 if( (bb.max[i]<=min[i]) || (max[i]<=bb.min[i]) )
00151 return false;
00152 }
00153
00154 return true;
00155 }
00156
00157
00158
00159
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
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
00182 bool operator==(const BoundingBox& bb) const { return min==bb.min && max==bb.max; }
00183
00184
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