00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_OBB_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_OBB_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/core/geometry/geometry_compute_obb_aabb.h>
00014
00015 #include <OpenTissue/core/function/function_signed_distance_function.h>
00016 #include <OpenTissue/utility/utility_class_id.h>
00017 #include <OpenTissue/core/math/math_rotation.h>
00018 #include <OpenTissue/core/math/math_precision.h>
00019 #include <cassert>
00020
00021 namespace OpenTissue
00022 {
00023
00024 namespace geometry
00025 {
00026
00030 template< typename math_types_ >
00031 class OBB
00032 : public VolumeShape< math_types_ >
00033 , public function::SignedDistanceFunction< math_types_ >
00034 , public OpenTissue::utility::ClassID< OBB<math_types_> >
00035 {
00036 public:
00037
00038 typedef math_types_ math_types;
00039 typedef typename math_types::value_traits value_traits;
00040 typedef typename math_types::real_type real_type;
00041 typedef typename math_types::vector3_type vector3_type;
00042 typedef typename math_types::matrix3x3_type matrix3x3_type;
00043
00044 typedef typename math_types::coordsys_type coordsys_type;
00045
00046 protected:
00047
00048 matrix3x3_type m_R;
00049 vector3_type m_T;
00050 vector3_type m_ext;
00051 vector3_type m_eps;
00052
00053 public:
00054
00055 void compute_surface_points(std::vector<vector3_type> & points) const
00056 {
00057 vector3_type v1(m_R(0,0),m_R(1,0),m_R(2,0));
00058 vector3_type v2(m_R(0,1),m_R(1,1),m_R(2,1));
00059 vector3_type v3(m_R(0,2),m_R(1,2),m_R(2,2));
00060
00061 v1 *= m_ext[0];
00062 v2 *= m_ext[1];
00063 v3 *= m_ext[2];
00064
00065 vector3_type p000 = m_T - v1 - v2 - v3;
00066 vector3_type p001 = m_T + v1 - v2 - v3;
00067 vector3_type p010 = m_T - v1 + v2 - v3;
00068 vector3_type p011 = m_T + v1 + v2 - v3;
00069 vector3_type p100 = m_T - v1 - v2 + v3;
00070 vector3_type p101 = m_T + v1 - v2 + v3;
00071 vector3_type p110 = m_T - v1 + v2 + v3;
00072 vector3_type p111 = m_T + v1 + v2 + v3;
00073
00074 points.push_back(p000);
00075 points.push_back(p001);
00076 points.push_back(p010);
00077 points.push_back(p011);
00078 points.push_back(p100);
00079 points.push_back(p101);
00080 points.push_back(p110);
00081 points.push_back(p111);
00082 }
00083
00084 vector3_type center() const { return vector3_type(m_T); }
00085 vector3_type const & eps() const { return m_eps; }
00086 vector3_type const & ext() const { return m_ext; }
00087 matrix3x3_type const & orientation() const { return m_R; }
00088
00089 public:
00090
00091 size_t const class_id() const { return OpenTissue::utility::ClassID<OpenTissue::geometry::OBB<math_types_> >::class_id(); }
00092
00093 OBB()
00094 {
00095 using OpenTissue::math::diag;
00096
00097 m_T.clear();
00098 m_R = diag(value_traits::one());
00099 m_ext = vector3_type(value_traits::half(),value_traits::half(),value_traits::half());
00100 m_eps = vector3_type(m_ext);
00101 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00102 m_eps += vector3_type(epsilon,epsilon,epsilon);
00103 }
00104
00105 virtual ~OBB() {}
00106
00107 explicit OBB(vector3_type const & T,matrix3x3_type const & R,vector3_type const & a) { set(T,R,a); }
00108
00109 OBB(OBB const & box) { set(box); }
00110
00111 public:
00112
00120 void set(OBB const & box)
00121 {
00122 m_T = box.m_T;
00123 m_R = box.m_R;
00124 m_ext = box.m_ext;
00125 m_eps = box.m_eps;
00126 }
00127
00136 void set(vector3_type const & T,matrix3x3_type const & R,vector3_type const & a)
00137 {
00138 m_T = T;
00139 m_R = R;
00140 m_ext = a;
00141 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00142 m_eps[0] = a[0] + epsilon;
00143 m_eps[1] = a[1] + epsilon;
00144 m_eps[2] = a[2] + epsilon;
00145 }
00146
00147 void init(real_type const & width,real_type const & height,real_type const & depth)
00148 {
00149 m_ext = vector3_type(width,height,depth)/value_traits::two();
00150 m_eps = m_ext;
00151 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00152 m_eps += vector3_type(epsilon,epsilon,epsilon);
00153 }
00154
00155 void place(vector3_type const & T,matrix3x3_type const & R)
00156 {
00157 this->m_R = R;
00158 this->m_T = T;
00159 }
00160
00161 void place(coordsys_type const & X)
00162 {
00163 this->m_R = X.Q();
00164 this->m_T = X.T();
00165 }
00166
00174 void xform(vector3_type const & T,matrix3x3_type const & R)
00175 {
00176 this->m_T = (R * this->m_T) + T;
00177 this->m_R = R * this->m_R;
00178 }
00179
00185 void xform(coordsys_type const & X)
00186 {
00187 X.xform_point(m_T);
00188 X.xform_matrix(m_R);
00189 }
00190
00197 real_type diameter() const
00198 {
00199 using OpenTissue::math::length;
00200
00201 return value_traits::two()*length(m_ext);
00202 }
00203
00209 real_type area() const
00210 {
00211 return value_traits::eight()*(m_ext*m_ext);
00212 }
00213
00219 real_type volume() const
00220 {
00221 return value_traits::eight()*m_ext[0]*m_ext[1]*m_ext[2];
00222 }
00223
00224 void translate(vector3_type const & T)
00225 {
00226 m_T += T;
00227 }
00228
00229 void rotate(matrix3x3_type const & R)
00230 {
00231 m_R = R * m_R;
00232 }
00233
00234 void scale(real_type const & s)
00235 {
00236 assert(s>=value_traits::zero() || !"OBB::scale: scale value must be non-negative");
00237 m_ext *= s;
00238 real_type epsilon = math::working_precision<real_type>();
00239 m_eps[0] = m_ext[0] + epsilon;
00240 m_eps[1] = m_ext[1] + epsilon;
00241 m_eps[2] = m_ext[2] + epsilon;
00242 }
00243
00244 vector3_type get_support_point(vector3_type const & v) const
00245 {
00246 using OpenTissue::math::unit;
00247
00248 vector3_type dir,p,tmp;
00249 p.clear();
00250 dir = unit(v);
00251
00252 tmp = vector3_type( m_R(0,0), m_R(1,0), m_R(2,0))* m_ext(0);
00253 real_type tst = tmp * dir;
00254
00255 real_type sign = value_traits::zero();
00256
00257 if(tst>value_traits::zero())
00258 sign = value_traits::one();
00259 if(tst<value_traits::zero())
00260 sign = -value_traits::one();
00261
00262 if(tst==value_traits::zero())
00263 sign = value_traits::zero();
00264
00265 p += tmp*sign;
00266
00267 tmp = vector3_type( m_R(0,1), m_R(1,1), m_R(2,1))* m_ext(1);
00268 tst = tmp * dir;
00269 if(tst>value_traits::zero())
00270 sign = value_traits::one();
00271 if(tst<value_traits::zero())
00272 sign = -value_traits::one();
00273
00274 if(tst==value_traits::zero())
00275 sign = value_traits::zero();
00276 p += tmp*sign;
00277
00278 tmp = vector3_type( m_R(0,2), m_R(1,2), m_R(2,2))* m_ext(2);
00279 tst = tmp * dir;
00280 if(tst>value_traits::zero())
00281 sign = value_traits::one();
00282 if(tst<value_traits::zero())
00283 sign = -value_traits::one();
00284
00285 if(tst==value_traits::zero())
00286 sign = value_traits::zero();
00287 p += tmp*sign;
00288
00289 p += m_T;
00290 return p;
00291 }
00292
00293 public:
00294
00295 real_type evaluate(vector3_type const & x) const
00296 {
00297 using std::fabs;
00298 using OpenTissue::math::trans;
00299 using OpenTissue::math::max_value;
00300
00301 vector3_type const p = trans(m_R)*(x-m_T);
00302 vector3_type const tmp = fabs(p)-m_ext;
00303 real_type const res = max_value(tmp);
00304 return res;
00305 }
00306
00307 vector3_type gradient(vector3_type const & ) const
00308 {
00309
00310 return vector3_type();
00311 }
00312
00313 vector3_type normal(vector3_type const & ) const
00314 {
00315
00316 return vector3_type();
00317 }
00318
00319 real_type signed_distance(vector3_type const & ) const
00320 {
00321
00322 return value_traits::zero();
00323 }
00324
00336 void compute_collision_aabb(
00337 vector3_type const & r
00338 , matrix3x3_type const & R
00339 , vector3_type & min_coord
00340 , vector3_type & max_coord
00341 ) const
00342 {
00343 OpenTissue::geometry::compute_obb_aabb(r, R, this->ext(), min_coord, max_coord);
00344 }
00345
00346
00347 };
00348
00349 }
00350
00351 }
00352
00353
00354 #endif