00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_AABB_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_AABB_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/geometry_volume_shape.h>
00013 #include <OpenTissue/utility/utility_class_id.h>
00014
00015 #include <algorithm>
00016 #include <cassert>
00017
00018
00019 namespace OpenTissue
00020 {
00021
00022 namespace geometry
00023 {
00024
00028 template< typename math_types_ >
00029 class AABB
00030 : public VolumeShape< math_types_ >
00031 , public OpenTissue::utility::ClassID< AABB<math_types_> >
00032 {
00033 public:
00034
00035 typedef math_types_ math_types;
00036 typedef typename math_types::value_traits value_traits;
00037 typedef typename math_types::real_type real_type;
00038 typedef typename math_types::vector3_type vector3_type;
00039 typedef typename math_types::matrix3x3_type matrix3x3_type;
00040 typedef typename math_types::quaternion_type quaternion_type;
00041
00042 public:
00043
00044 vector3_type m_min;
00045 vector3_type m_max;
00046
00047 public:
00048
00049 size_t const class_id() const { return OpenTissue::utility::ClassID<OpenTissue::geometry::AABB<math_types_> >::class_id(); }
00050
00051 AABB()
00052 {
00053 m_min.clear();
00054 m_max.clear();
00055 }
00056
00057 explicit AABB(
00058 real_type const & xmin
00059 , real_type const & ymin
00060 , real_type const & zmin
00061 , real_type const & xmax
00062 , real_type const & ymax
00063 , real_type const & zmax
00064 )
00065 {
00066 set(xmin,ymin,zmin,xmax,ymax,zmax);
00067 }
00068
00069 explicit AABB( vector3_type const & pmin_v, vector3_type const & pmax_v) { set(pmin_v,pmax_v); }
00070
00071 virtual ~AABB() {}
00072
00073 public:
00074
00075 void compute_surface_points(std::vector<vector3_type> & points) const
00076 {
00077 vector3_type dia;
00078 dia = m_max - m_min;
00079
00080 vector3_type p000 = m_min;
00081 vector3_type p001 = m_min + vector3_type( dia[0], value_traits::zero(), value_traits::zero());
00082 vector3_type p010 = m_min + vector3_type(value_traits::zero(), dia[1], value_traits::zero());
00083 vector3_type p011 = m_min + vector3_type( dia[0], dia[1], value_traits::zero());
00084 vector3_type p100 = m_min + vector3_type(value_traits::zero(), value_traits::zero(), dia[2]);
00085 vector3_type p101 = m_min + vector3_type( dia[0], value_traits::zero(), dia[2]);
00086 vector3_type p110 = m_min + vector3_type(value_traits::zero(), dia[1], dia[2]);
00087 vector3_type p111 = m_min + vector3_type( dia[0], dia[1], dia[2]);
00088
00089 points.push_back(p000);
00090 points.push_back(p001);
00091 points.push_back(p010);
00092 points.push_back(p011);
00093 points.push_back(p100);
00094 points.push_back(p101);
00095 points.push_back(p110);
00096 points.push_back(p111);
00097 }
00098
00099 vector3_type center() const { return vector3_type( (m_max+m_min)/value_traits::two() ); }
00100
00101 public:
00108 void set(AABB const & other_aabb)
00109 {
00110 this->m_min = other_aabb.m_min;
00111 this->m_max = other_aabb.m_max;
00112 }
00113
00114 void set( vector3_type const & pmin_v, vector3_type const & pmax_v)
00115 {
00116 assert(pmin_v[0] <= pmax_v[0] || !"AABB.set(): minimum must be less than or equal to maximum");
00117 assert(pmin_v[1] <= pmax_v[1] || !"AABB.set(): minimum must be less than or equal to maximum");
00118 assert(pmin_v[2] <= pmax_v[2] || !"AABB.set(): minimum must be less than or equal to maximum");
00119 m_min = pmin_v;
00120 m_max = pmax_v;
00121 }
00122
00133 void set(
00134 real_type const & xmin
00135 , real_type const & ymin
00136 , real_type const & zmin
00137 , real_type const & xmax
00138 , real_type const & ymax
00139 , real_type const & zmax
00140 )
00141 {
00142 assert(xmin<=xmax || !"AABB.set(): minimum must be less than or equal to maximum");
00143 assert(ymin<=ymax || !"AABB.set(): minimum must be less than or equal to maximum");
00144 assert(zmin<=zmax || !"AABB.set(): minimum must be less than or equal to maximum");
00145 m_min = vector3_type(xmin,ymin,zmin);
00146 m_max = vector3_type(xmax,ymax,zmax);
00147 }
00148
00159 void extent(
00160 real_type const & xmin
00161 , real_type const & ymin
00162 , real_type const & zmin
00163 , real_type const & width
00164 , real_type const & height
00165 , real_type const & depth
00166 )
00167 {
00168 assert(width>=0 || !"AABB.extent(): width must be non-negative");
00169 assert(height>=0 || !"AABB.extent(): height must be non-negative");
00170 assert(depth>=0 || !"AABB.extent(): depth must be non-negative");
00171 m_min = vector3_type(xmin,ymin,zmin);
00172 m_max = vector3_type(xmin+width,ymin+height,zmin+depth);
00173 }
00174
00175 public:
00176
00177 real_type const & x() const { return m_min[0]; }
00178 real_type const & y() const { return m_min[1]; }
00179 real_type const & z() const { return m_min[2]; }
00180 real_type w() const { return m_max[0] - m_min[0]; }
00181 real_type h() const { return m_max[1] - m_min[1]; }
00182 real_type d() const { return m_max[2] - m_min[2]; }
00183
00184 vector3_type & min() { return m_min; }
00185 vector3_type & max() { return m_max; }
00186 vector3_type const & min() const { return m_min; }
00187 vector3_type const & max() const { return m_max; }
00188
00198 void update(vector3_type const & n0,vector3_type const & n1, vector3_type const & n2)
00199 {
00200 using std::min;
00201 using std::max;
00202
00203 m_min[0] = min(n2[0],min(n1[0],n0[0]));
00204 m_min[1] = min(n2[1],min(n1[1],n0[1]));
00205 m_min[2] = min(n2[2],min(n1[2],n0[2]));
00206 m_max[0] = max(n2[0],max(n1[0],n0[0]));
00207 m_max[1] = max(n2[1],max(n1[1],n0[1]));
00208 m_max[2] = max(n2[2],max(n1[2],n0[2]));
00209 }
00210
00221 void update(vector3_type const & n0,vector3_type const & n1,vector3_type const & n2, vector3_type const & n3)
00222 {
00223 using std::min;
00224 using std::max;
00225
00226 m_min[0] = min(n3[0],min(n2[0],min(n1[0],n0[0])));
00227 m_min[1] = min(n3[1],min(n2[1],min(n1[1],n0[1])));
00228 m_min[2] = min(n3[2],min(n2[2],min(n1[2],n0[2])));
00229 m_max[0] = max(n3[0],max(n2[0],max(n1[0],n0[0])));
00230 m_max[1] = max(n3[1],max(n2[1],max(n1[1],n0[1])));
00231 m_max[2] = max(n3[2],max(n2[2],max(n1[2],n0[2])));
00232 }
00233
00242 void update(AABB const & A,AABB const & B)
00243 {
00244 using std::min;
00245 using std::max;
00246
00247 m_min[0] = min(A.m_min[0],B.m_min[0]);
00248 m_min[1] = min(A.m_min[1],B.m_min[1]);
00249 m_min[2] = min(A.m_min[2],B.m_min[2]);
00250 m_max[0] = max(A.m_max[0],B.m_max[0]);
00251 m_max[1] = max(A.m_max[1],B.m_max[1]);
00252 m_max[2] = max(A.m_max[2],B.m_max[2]);
00253 }
00254
00260 real_type volume() const
00261 {
00262 vector3_type vd = m_max-m_min;
00263 return vd[0]*vd[1]*vd[2];
00264 }
00265
00266 real_type area() const
00267 {
00268 vector3_type vd = m_max-m_min;
00269 return 2*vd[0]*vd[1] + 2*vd[0]*vd[2] + 2*vd[2]*vd[1];
00270 }
00271
00272 real_type diameter() const
00273 {
00274 vector3_type vd = m_max-m_min;
00275 return length(vd);
00276 }
00277
00278 void translate(vector3_type const & T)
00279 {
00280 m_max += T;
00281 m_min += T;
00282 }
00283
00284 void rotate(matrix3x3_type const & ) { }
00285
00286 void scale(real_type const & s)
00287 {
00288 assert(s>=value_traits::zero() || !"AABB::scale: s must be non-negative");
00289 vector3_type c = center();
00290 m_min -= c;
00291 m_max -= c;
00292 m_min *= s;
00293 m_max *= s;
00294 m_min += c;
00295 m_max += c;
00296 }
00297
00298 vector3_type get_support_point(vector3_type const & v) const
00299 {
00300 vector3_type dir = unit(v);
00301 vector3_type ext = (m_max - m_min)/2.;
00302 vector3_type c = center();
00303 vector3_type p(0,0,0);
00304
00305 real_type sign = value_traits::zero();
00306 real_type tst = ext[0] * dir[0];
00307 if(tst>0)
00308 sign = value_traits::one();
00309 else if(tst<0)
00310 sign = -value_traits::one();
00311 else
00312 sign = value_traits::zero();
00313 p[0] += sign * ext[0];
00314
00315 tst = ext[1] * dir[1];
00316 if(tst>0)
00317 sign = value_traits::one();
00318 else if(tst<0)
00319 sign = -value_traits::one();
00320 else
00321 sign = value_traits::zero();
00322 p[1] += sign * ext[1];
00323
00324 tst = ext[2] * dir[2];
00325 if(tst>0)
00326 sign = value_traits::one();
00327 else if(tst<0)
00328 sign = -value_traits::one();
00329 else
00330 sign = value_traits::zero();
00331 p[2] += sign * ext[2];
00332 p += c;
00333 return p;
00334 }
00335
00336
00337
00349 void compute_collision_aabb(
00350 vector3_type const & r
00351 , matrix3x3_type const &
00352 , vector3_type & min_coord
00353 , vector3_type & max_coord
00354 ) const
00355 {
00356 min_coord = r + this->min();
00357 max_coord = r + this->max();
00358 }
00359
00360
00361 };
00362
00363 }
00364
00365 }
00366
00367
00368 #endif