00001 #ifndef _BOUNDING_BOX_H_
00002 #define _BOUNDING_BOX_H_
00003
00004 #define NOMINMAX 1
00005 #include "defs.h"
00006 #include "Matrix.h"
00007 #include "Vec3D.h"
00008 #include "MathHelper.h"
00009 #include "Ray.h"
00010
00011 #include <string>
00012 #include <ostream>
00013 #include <limits>
00014
00015 namespace FemViewer {
00016
00017
00018 template<typename T> class Ray;
00019 class BBox3D;
00020 BBox3D operator*(const Matrix<float>& pMatrix,
00021 const BBox3D& pBBox3D);
00022
00023 template<typename T>
00024 struct AAbb {
00025 union {
00026 struct { CVec3<T> mn, mx; };
00027 CVec3<T> bounds[2];
00028 T coords[6];
00029 struct {
00030 T x_min, y_min, z_min;
00031 T x_max, y_max, z_max;
00032 };
00033 };
00034 AAbb()
00035 : x_min(std::numeric_limits<T>::max())
00036 , y_min(std::numeric_limits<T>::max())
00037 , z_min(std::numeric_limits<T>::max())
00038 , x_max(-std::numeric_limits<T>::max())
00039 , y_max(-std::numeric_limits<T>::max())
00040 , z_max(-std::numeric_limits<T>::max())
00041 {}
00042 AAbb(T x0,T y0,T z0,T x1,T y1,T z1)
00043 : x_min(x0),y_min(y0),z_min(z0)
00044 , x_max(x1),y_max(y1),z_max(z1)
00045 {}
00046 AAbb(const Vec3<T>& l,const Vec3<T>& u) : mn(l), mx(u) {}
00047 AAbb(const AAbb& rh) : mn(rh.mn), mx(rh.mx) {}
00048 void operator=(const AAbb& rh) { mn = rh.mn; mx = rh.mx; }
00049 };
00050
00051 typedef AAbb<float> AAbbf;
00052 typedef AAbb<double> AAbbd;
00053
00054
00055
00056 class BBox3D : public AAbbf
00057 {
00058 bool _aInitialized;
00059 public:
00060
00061 BBox3D();
00062 BBox3D(const BBox3D& pBBox3D);
00063 explicit BBox3D(const Vec3D& pPoint);
00064 explicit BBox3D(const fvmath::Vec3f& pCenter, const float size);
00065 explicit BBox3D(const fvmath::Vec3f& pLower,const fvmath::Vec3f& pUpper);
00066 explicit BBox3D(const Vec3D& pLower, const Vec3D& pUpper);
00067 template<class T>
00068 explicit BBox3D(const fvmath::Vec3<T>& l,const fvmath::Vec3<T>& u);
00069 ~BBox3D () {;}
00070 Vec3f & operator [](size_t idx) { return bounds[idx]; }
00071 const Vec3f & operator [](size_t idx) const { return bounds[idx]; }
00072 void Reset();
00073
00074 void dumpCharacteristics (std::ostream& pOstream,
00075 const std::string& pIndentation,
00076 const Matrix<float>& pTransformation);
00077
00078 void render () const;
00079
00080
00081 CVec3f getCenter() const;
00082 template<class T>
00083 fvmath::CVec3<T> center() const;
00084 float getCircumscribedSphereRadius() const;
00085
00086 float Xmin() const { return x_min; }
00087 float Ymin() const { return y_min; }
00088 float Zmin() const { return z_min; }
00089 float Xmax() const { return x_max; }
00090 float Ymax() const { return y_max; }
00091 float Zmax() const { return z_max; }
00092
00093
00094
00095 void minX(float x) { x_min = x; }
00096 void maxX(float x) { x_max = x; }
00097 void minY(float y) { y_min = y; }
00098 void maxY(float y) { y_max = y; }
00099 void minZ(float z) { z_min = z; }
00100 void maxZ(float z) { z_max = z; }
00101
00102 Vec3D lower() const {
00103 return Vec3D(x_min,y_min,z_min);
00104 }
00105
00106 Vec3D upper() const {
00107 return Vec3D(x_max,y_max,z_max);
00108 }
00109 template<class T>
00110 void move(const fvmath::Vec3<T>& mv);
00111
00112 bool IsInside(const Vec3D& pt) const
00113 {
00114 return( (pt._x() >= (x_min - 0.001)) && (pt._x() <= (x_max + 0.001)) &&
00115 (pt._y() >= (y_min - 0.001)) && (pt._y() <= (y_max + 0.001)) &&
00116 (pt._z() >= (z_min - 0.001)) && (pt._z() <= (z_max + 0.001)) );
00117 }
00118
00119 template<class T>
00120 bool IsInside(const fvmath::Vec3<T>& pt) const
00121 {
00122 return( (pt.x >= (x_min - 0.001)) && (pt.x <= (x_max + 0.001)) &&
00123 (pt.y >= (y_min - 0.001)) && (pt.y <= (y_max + 0.001)) &&
00124 (pt.z >= (z_min - 0.001)) && (pt.z <= (z_max + 0.001)) );
00125 }
00126
00127 BBox3D& operator= (const BBox3D& pBBox3D);
00128 BBox3D operator+ (const BBox3D& pBBox3D) const;
00129 BBox3D operator+ (const Vec3D& pPoint) const;
00130 BBox3D& operator+=(const BBox3D& pBBox3D);
00131 BBox3D& operator+=(const Vec3D& pPoint );
00132 template<class T>
00133 inline BBox3D& operator+=(const fvmath::Vec3<T>& pPoint)
00134 {
00135 return *this;
00136 }
00137
00138 template<class T>
00139 inline BBox3D& operator+=(const fvmath::Vec3<T>* pPoint)
00140 {
00141 this->bounds[0] = fv_min(pPoint[0],this->bounds[0]);
00142 this->bounds[1] = fv_min(pPoint[1],this->bounds[1]);
00143 this->bounds[2] = fv_min(pPoint[2],this->bounds[2]);
00144 this->bounds[3] = fv_max(pPoint[0],this->bounds[3]);
00145 this->bounds[4] = fv_max(pPoint[1],this->bounds[4]);
00146 this->bounds[5] = fv_max(pPoint[2],this->bounds[5]);
00147 return *this;
00148 }
00149
00150 inline uint8_t majorAxis(float *pSize) const {
00151 pSize[0] = x_max - x_min;
00152 pSize[1] = y_max - y_min;
00153 pSize[2] = z_max - z_min;
00154 uint8_t major = 0;
00155 if (pSize[0] < pSize[1]) major = 1;
00156 if (pSize[1] < pSize[1]) major = 2;
00157 return major;
00158 }
00159
00160 inline float maxDim() const {
00161
00162 if(!_aInitialized) return 0.0f;
00163 const float ux = fvmath::abs(x_max-x_min);
00164 const float uy = fvmath::abs(y_max-y_min);
00165 const float uz = fvmath::abs(z_max-z_min);
00166
00167 return fv_max(fv_max(ux,uy),uz);
00168 }
00169
00170 inline float minDim() const {
00171 if(!_aInitialized) return 0.0f;
00172 const float ux = fvmath::abs(x_max-x_min);
00173 const float uy = fvmath::abs(y_max-y_min);
00174 const float uz = fvmath::abs(z_max-z_min);
00175
00176 return fv_min(fv_min(ux,uy),uz);
00177 }
00178 inline float * data(void) { return coords; }
00179 inline bool isInitialized() const { return _aInitialized; }
00180 inline void setInitialized(const float flg=true) { _aInitialized = flg; }
00181
00182 bool intersect(const Ray<float>& r) const;
00183
00184 public:
00185 class Edge {
00186 public:
00187 Edge() : _begin(0), _end(0) {}
00188 Edge(unsigned index0, unsigned index1) : _begin(index0), _end(index1){}
00189 unsigned int begin() const { return _begin; }
00190 unsigned int end() const { return _end; }
00191
00192 private:
00193 unsigned int _begin, _end;
00194 };
00195
00196 template<typename T = float>
00197 static uint8_t InitVertices(const BBox3D* pBBox3D,CVec3<T> *pVertices);
00198 private:
00199
00200 friend BBox3D operator*(const Matrix<float>& pMatrix,
00201 const BBox3D& pBBox3D);
00202 friend BBox3D operator*(const BBox3D& pBBox3D, const float zoom);
00203
00204 friend std::ostream& operator <<(std::ostream& os, const BBox3D& pBBox);
00205
00206 };
00207
00208 template<class T>
00209 inline BBox3D::BBox3D(const fvmath::Vec3<T>& l,const fvmath::Vec3<T>& u)
00210 : AAbb(l,u)
00211 , _aInitialized(true)
00212 {
00213 FV_ASSERT(x_max >= x_min);
00214 FV_ASSERT(y_max >= y_min);
00215 FV_ASSERT(z_max >= z_min);
00216 }
00217
00218 template<class T>
00219 fvmath::CVec3<T> BBox3D::center() const
00220 {
00221 fvmath::CVec3<T> lcen;
00222
00223 if (_aInitialized) {
00224 lcen.x = 0.5 * (x_min + x_max);
00225 lcen.y = 0.5 * (y_min + y_max);
00226 lcen.z = 0.5 * (z_min + z_max);
00227 }
00228
00229 return lcen;
00230 }
00231
00232 template<class T>
00233 inline void BBox3D::move(const fvmath::Vec3<T>& mv)
00234 {
00235 if (_aInitialized) {
00236 x_min += mv.x;
00237 x_max += mv.x;
00238 y_min += mv.y;
00239 y_max += mv.y;
00240 z_min += mv.z;
00241 z_max += mv.z;
00242 }
00243 }
00244
00245 template<>
00246 inline BBox3D& BBox3D::operator+=(const fvmath::Vec3f& pPoint)
00247 {
00248 if (_aInitialized) {
00249 x_min = fv_min(x_min, pPoint.x);
00250 x_max = fv_max(x_max, pPoint.x);
00251 y_min = fv_min(y_min, pPoint.y);
00252 y_max = fv_max(y_max, pPoint.y);
00253 z_min = fv_min(z_min, pPoint.z);
00254 z_max = fv_max(z_max, pPoint.z);
00255 }
00256 else {
00257 x_min = x_max = pPoint.x;
00258 y_min = y_max = pPoint.y;
00259 z_min = z_max = pPoint.z;
00260 _aInitialized = true;
00261 }
00262
00263 FV_ASSERT(x_max >= x_min);
00264 FV_ASSERT(y_max >= y_min);
00265 FV_ASSERT(z_max >= z_min);
00266
00267 return *this;
00268 }
00269
00270 template<>
00271 inline BBox3D& BBox3D::operator+=(const fvmath::Vec3d& pPoint)
00272 {
00273 float x = static_cast<float>(pPoint.x);
00274 float y = static_cast<float>(pPoint.y);
00275 float z = static_cast<float>(pPoint.z);
00276 if (_aInitialized) {
00277 x_min = fv_min(x_min, x);
00278 x_max = fv_max(x_max, x);
00279 y_min = fv_min(y_min, y);
00280 y_max = fv_max(y_max, y);
00281 z_min = fv_min(z_min, z);
00282 z_max = fv_max(z_max, z);
00283 }
00284 else {
00285 x_min = x_max = x;
00286 y_min = y_max = y;
00287 z_min = z_max = z;
00288 _aInitialized = true;
00289 }
00290
00291 FV_ASSERT(x_max >= x_min);
00292 FV_ASSERT(y_max >= y_min);
00293 FV_ASSERT(z_max >= z_min);
00294
00295 return *this;
00296
00297 }
00298
00299 inline bool BBox3D::intersect(const Ray<float>& r) const
00300 {
00301 float tmin, tmax, tymin, tymax, tzmin, tzmax;
00302 tmin = (bounds[r.sign[0]].x - r.orig.x) * r.invdir.x;
00303 tmax = (bounds[1 - r.sign[0]].x - r.orig[0]) * r.invdir.x;
00304 tymin = (bounds[r.sign[1]].y - r.orig.y) * r.invdir.y;
00305 tymax = (bounds[1 - r.sign[1]].y - r.orig.y) * r.invdir.y;
00306 if ((tmin > tymax) || (tymin > tmax))
00307 return false;
00308 if (tymin > tmin)
00309 tmin = tymin;
00310 if (tymax < tmax)
00311 tmax = tymax;
00312 tzmin = (bounds[r.sign[2]].z - r.orig.z) * r.invdir.z;
00313 tzmax = (bounds[1-r.sign[2]].z - r.orig.z) * r.invdir.z;
00314 if ((tmin > tzmax) || (tzmin > tmax))
00315 return false;
00316 if (tzmin > tmin)
00317 tmin = tzmin;
00318 if (tzmax < tmax)
00319 tmax = tzmax;
00320 if (tmin > r.tmin) r.tmin = tmin;
00321 if (tmax < r.tmax) r.tmax = tmax;
00322
00323 return true;
00324 }
00325
00326 template<typename T>
00327 uint8_t BBox3D::InitVertices(const BBox3D *pBBox3D,CVec3<T>* pVertices)
00328 {
00329 pVertices[0] = CVec3<T>(pBBox3D->Xmin(),pBBox3D->Ymin(),pBBox3D->Zmin());
00330 pVertices[1] = CVec3<T>(pBBox3D->Xmax(),pBBox3D->Ymin(),pBBox3D->Zmin());
00331 pVertices[2] = CVec3<T>(pBBox3D->Xmax(),pBBox3D->Ymax(),pBBox3D->Zmin());
00332 pVertices[3] = CVec3<T>(pBBox3D->Xmin(),pBBox3D->Ymax(),pBBox3D->Zmin());
00333 pVertices[4] = CVec3<T>(pBBox3D->Xmin(),pBBox3D->Ymin(),pBBox3D->Zmax());
00334 pVertices[5] = CVec3<T>(pBBox3D->Xmax(),pBBox3D->Ymin(),pBBox3D->Zmax());
00335 pVertices[6] = CVec3<T>(pBBox3D->Xmax(),pBBox3D->Ymax(),pBBox3D->Zmax());
00336 pVertices[7] = CVec3<T>(pBBox3D->Xmin(),pBBox3D->Ymax(),pBBox3D->Zmax());
00337 return(8);
00338 }
00339
00340
00341
00342
00343 class Mesh;
00344 extern const BBox3D::Edge edges[];
00345 extern BBox3D getModelBoundingBox(void);
00346 extern const BBox3D& getModelBoundingBoxd_omp(Mesh* pmesh);
00347 extern void min_sub_tab(long start_point, long n_points, double *l_mnmx);
00348
00349
00350
00351 }
00352 #endif // _BOUNDING_BOX_H_