00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_ELLIPSOID_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_ELLIPSOID_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014 #include <OpenTissue/core/geometry/geometry_volume_shape.h>
00015 #include <OpenTissue/core/geometry/geometry_compute_obb_aabb.h>
00016 #include <OpenTissue/utility/utility_class_id.h>
00017
00018 #include <cmath>
00019
00020 namespace OpenTissue
00021 {
00022
00023 namespace geometry
00024 {
00025
00029 template< typename math_types_ >
00030 class Ellipsoid
00031 : public VolumeShape< math_types_ >
00032 , public OpenTissue::utility::ClassID< Ellipsoid<math_types_> >
00033 {
00034 public:
00035
00036 typedef math_types_ math_types;
00037 typedef typename math_types::index_type index_type;
00038 typedef typename math_types::value_traits value_traits;
00039 typedef typename math_types::real_type real_type;
00040 typedef typename math_types::vector3_type vector3_type;
00041 typedef typename math_types::matrix3x3_type matrix3x3_type;
00042 typedef typename math_types::quaternion_type quaternion_type;
00043 typedef Ellipsoid<math_types_> ellipsoid_type;
00044
00045 protected:
00046
00047 vector3_type m_center;
00048 vector3_type m_axis0;
00049 vector3_type m_axis1;
00050 vector3_type m_axis2;
00051 real_type m_radius0;
00052 real_type m_radius1;
00053 real_type m_radius2;
00054
00055 public:
00056
00057 size_t const class_id() const { return OpenTissue::utility::ClassID<OpenTissue::geometry::Ellipsoid<math_types_> >::class_id(); }
00058
00059 Ellipsoid()
00060 : m_center(value_traits::zero(),value_traits::zero(),value_traits::zero())
00061 , m_axis0(value_traits::one(),value_traits::zero(),value_traits::zero())
00062 , m_axis1(value_traits::zero(),value_traits::one(),value_traits::zero())
00063 , m_axis2(value_traits::zero(),value_traits::zero(),value_traits::one())
00064 , m_radius0(value_traits::one())
00065 , m_radius1(value_traits::one())
00066 , m_radius2(value_traits::one())
00067 {}
00068
00069 virtual ~Ellipsoid() {}
00070
00071 public:
00072
00073 Ellipsoid & operator=(ellipsoid_type const & ellipsoid)
00074 {
00075 m_center = ellipsoid.m_center;
00076 m_axis0 = ellipsoid.m_axis0;
00077 m_axis1 = ellipsoid.m_axis1;
00078 m_axis2 = ellipsoid.m_axis2;
00079 m_radius0 = ellipsoid.m_radius0;
00080 m_radius1 = ellipsoid.m_radius1;
00081 m_radius2 = ellipsoid.m_radius2;
00082 return *this;
00083 }
00084
00085 public:
00086
00087 real_type & radius0() { return m_radius0; }
00088 real_type & radius1() { return m_radius1; }
00089 real_type & radius2() { return m_radius2; }
00090 real_type const & radius0() const { return m_radius0; }
00091 real_type const & radius1() const { return m_radius1; }
00092 real_type const & radius2() const { return m_radius2; }
00093 vector3_type & center() { return m_center; }
00094 vector3_type center() const { return m_center; }
00095 vector3_type & axis0() { return m_axis0; }
00096 vector3_type & axis1() { return m_axis1; }
00097 vector3_type & axis2() { return m_axis2; }
00098 vector3_type const & axis0() const { return m_axis0; }
00099 vector3_type const & axis1() const { return m_axis1; }
00100 vector3_type const & axis2() const { return m_axis2; }
00101
00102
00110 real_type & radius(index_type idx)
00111 {
00112 assert(idx>=0 || !"Ellipsoid::radius(): Index out of bounds");
00113 assert(idx<3 || !"Ellipsoid::radius(): Index out of bounds");
00114 if(idx==0)
00115 return m_radius0;
00116 else if(idx==1)
00117 return m_radius1;
00118 return m_radius2;
00119 }
00120
00121
00129 real_type const & radius(index_type idx) const
00130 {
00131 assert(idx>=0 || !"Ellipsoid::radius(): Index out of bounds");
00132 assert(idx<3 || !"Ellipsoid::radius(): Index out of bounds");
00133 if(idx==0)
00134 return m_radius0;
00135 else if(idx==1)
00136 return m_radius1;
00137 return m_radius2;
00138 }
00139
00140
00148 vector3_type const & axis(index_type idx) const
00149 {
00150 assert(idx>=0 || !"Ellipsoid::axis(): Index out of bounds");
00151 assert(idx<3 || !"Ellipsoid::axis(): Index out of bounds");
00152 if(idx==0)
00153 return m_axis0;
00154 else if(idx==1)
00155 return m_axis1;
00156 return m_axis2;
00157 }
00158
00166 vector3_type & axis(index_type idx)
00167 {
00168 assert(idx>=0 || !"Ellipsoid::axis(): Index out of bounds");
00169 assert(idx<3 || !"Ellipsoid::axis(): Index out of bounds");
00170 if(idx==0)
00171 return m_axis0;
00172 else if(idx==1)
00173 return m_axis1;
00174 return m_axis2;
00175 }
00176
00177 void orientation(matrix3x3_type const & R)
00178 {
00179 m_axis0(0) = R(0,0);
00180 m_axis0(1) = R(1,0);
00181 m_axis0(2) = R(2,0);
00182
00183 m_axis1(0) = R(0,1);
00184 m_axis1(1) = R(1,1);
00185 m_axis1(2) = R(2,1);
00186
00187 m_axis2(0) = R(0,2);
00188 m_axis2(1) = R(1,2);
00189 m_axis2(2) = R(2,2);
00190 }
00191
00192 matrix3x3_type orientation() const
00193 {
00194 return matrix3x3_type(
00195 m_axis0(0), m_axis1(0), m_axis2(0)
00196 , m_axis0(1), m_axis1(1), m_axis2(1)
00197 , m_axis0(2), m_axis1(2), m_axis2(2)
00198 );
00199 }
00200
00201 public:
00202
00203 real_type volume() const { return (4.0/3.0)*value_traits::pi()*m_radius0*m_radius1*m_radius2; }
00204
00205 public:
00206
00228 void get_equation(matrix3x3_type & A,vector3_type & B,real_type & C)const
00229 {
00230 assert(m_radius0>value_traits::zero() || !"Ellipsoid::get_equation(): First radius was zero");
00231 assert(m_radius1>value_traits::zero() || !"Ellipsoid::get_equation(): Second radius was zero");
00232 assert(m_radius2>value_traits::zero() || !"Ellipsoid::get_equation(): Third radius was zero");
00233
00234
00235 real_type d0 = value_traits::one()/(m_radius0*m_radius0);
00236 real_type d1 = value_traits::one()/(m_radius1*m_radius1);
00237 real_type d2 = value_traits::one()/(m_radius2*m_radius2);
00238
00239 for(unsigned int i=0;i<3;++i)
00240 for(unsigned int j=0;j<3;++j)
00241 A(i,j) = m_axis0(i)*d0*m_axis0(j) + m_axis1(i)*d1*m_axis1(j) + m_axis2(i)*d2*m_axis2(j);
00242 B = - A*m_center;
00243 C = - m_center * B - value_traits::one();
00244 }
00245
00255 void set_equation(matrix3x3_type const & A,vector3_type const & B,real_type const & C)
00256 {
00257 using std::sqrt;
00258 using std::fabs;
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 matrix3x3_type M = inverse(A);
00292 m_center = -M*B;
00293 real_type normalization = -C - m_center*B;
00294 M = A;
00295 M /= normalization;
00296 matrix3x3_type V;
00297 vector3_type d;
00298 math::eigen(M,V,d);
00299
00300
00301
00302
00303 d(0) = d(0) < value_traits::zero() ? - d(0) : d(0);
00304 d(1) = d(1) < value_traits::zero() ? - d(1) : d(1);
00305 d(2) = d(2) < value_traits::zero() ? - d(2) : d(2);
00306
00307 m_radius0 = sqrt( value_traits::one()/fabs(d(0)) );
00308 m_radius1 = sqrt( value_traits::one()/fabs(d(1)) );
00309 m_radius2 = sqrt( value_traits::one()/fabs(d(2)) );
00310 m_axis0(0) = V(0,0); m_axis0(1) = V(1,0); m_axis0(2) = V(2,0);
00311 m_axis1(0) = V(0,1); m_axis1(1) = V(1,1); m_axis1(2) = V(2,1);
00312 m_axis2(0) = V(0,2); m_axis2(1) = V(1,2); m_axis2(2) = V(2,2);
00313 }
00314
00315 public:
00316
00323 void get_covariance(vector3_type & mean, matrix3x3_type & C)
00324 {
00325 mean = center;
00326 assert(m_radius0>value_traits::zero() || !"Ellipsoid::get_covariance(): radius of first axis was zero");
00327 assert(m_radius1>value_traits::zero() || !"Ellipsoid::get_covariance(): radius of second axis was zero");
00328 assert(m_radius2>value_traits::zero() || !"Ellipsoid::get_covariance(): radius of third axis was zero");
00329
00330 real_type d0 = value_traits::one()/(m_radius0*m_radius0);
00331 real_type d1 = value_traits::one()/(m_radius1*m_radius1);
00332 real_type d2 = value_traits::one()/(m_radius2*m_radius2);
00333
00334 for(unsigned int i=0;i<3;++i)
00335 for(unsigned int j=0;j<3;++j)
00336 C(i,j) = m_axis0(i)*d0*m_axis0(j) + m_axis1(i)*d1*m_axis1(j) + m_axis2(i)*d2*m_axis2(j);
00337 }
00338
00345 void set_covariance(vector3_type const & mean,matrix3x3_type const & C)
00346 {
00347 using std::sqrt;
00348 using std::fabs;
00349
00350 matrix3x3_type M,V;
00351 vector3_type d;
00352 M = C;
00353 math::eigen(M,V,d);
00354 assert(d(0)>value_traits::zero() || !"Ellipsoid::set_covariance(): first diagonal entry was zero");
00355 assert(d(1)>value_traits::zero() || !"Ellipsoid::set_covariance(): second diagonal entry was zero");
00356 assert(d(2)>value_traits::zero() || !"Ellipsoid::set_covariance(): third diagonal entry was zero");
00357
00358 m_radius0 = sqrt(value_traits::one()/fabs(d(0)));
00359 m_radius1 = sqrt(value_traits::one()/fabs(d(1)));
00360 m_radius2 = sqrt(value_traits::one()/fabs(d(2)));
00361 m_axis0(0) = V(0,0); m_axis0(1) = V(1,0); m_axis0(2) = V(2,0);
00362 m_axis1(0) = V(0,1); m_axis1(1) = V(1,1); m_axis1(2) = V(2,1);
00363 m_axis2(0) = V(0,2); m_axis2(1) = V(1,2); m_axis2(2) = V(2,2);
00364 m_center = mean;
00365 }
00366
00367 public:
00368
00375 void set_sphere(real_type const & radius,vector3_type const & center)
00376 {
00377 m_radius0 = m_radius1 = m_radius2 = radius;
00378 m_center = center;
00379 m_axis0 = vector3_type(value_traits::one(),value_traits::zero(),value_traits::zero());
00380 m_axis1 = vector3_type(value_traits::zero(),value_traits::one(),value_traits::zero());
00381 m_axis2 = vector3_type(value_traits::zero(),value_traits::zero(),value_traits::one());
00382 }
00383
00384 public:
00385
00391 template<typename point_container>
00392 void random_points(point_container & P)
00393 {
00394 unsigned int N = 2000;
00395 P.resize(N);
00396 for(unsigned int i=0;i<N;++i)
00397 {
00398 vector3_type p,pp;
00399 do
00400 {
00401 random(p,-value_traits::one(),value_traits::one());
00402 }
00403 while(p(0)==value_traits::zero() && p(1)==value_traits::zero() && p(2)==value_traits::zero());
00404
00405 p = unit(p);
00406 p(0) *= m_radius0;
00407 p(1) *= m_radius1;
00408 p(2) *= m_radius2;
00409 pp(0) = m_axis0(0) * p(0) + m_axis1(0) * p(1) + m_axis2(0) * p(2) + m_center(0);
00410 pp(1) = m_axis0(1) * p(0) + m_axis1(1) * p(1) + m_axis2(1) * p(2) + m_center(1);
00411 pp(2) = m_axis0(2) * p(0) + m_axis1(2) * p(1) + m_axis2(2) * p(2) + m_center(2);
00412 P[i] = pp;
00413 }
00414 }
00415
00416 public:
00417
00418 void translate(vector3_type const & T) { m_center = m_center + T; }
00419
00420 void rotate(matrix3x3_type const & R)
00421 {
00422 vector3_type tmp;
00423
00424 tmp = m_axis0;
00425 m_axis0 = R*tmp;
00426
00427 tmp = m_axis1;
00428 m_axis1 = R*tmp;
00429
00430 tmp = m_axis2;
00431 m_axis2 = R*tmp;
00432
00433 tmp = m_center;
00434 m_center = R*tmp;
00435 }
00436
00437 void scale(real_type const & s)
00438 {
00439 m_radius0 *= s;
00440 m_radius1 *= s;
00441 m_radius2 *= s;
00442 m_center *= s;
00443 }
00444
00445
00446 vector3_type get_support_point(vector3_type const & ) const { assert(false ||!"Ellipsoid::get_support_point(): Sorry not implemented!"); return vector3_type(); }
00447
00448 real_type area() const { assert(false ||!"Ellipsoid::area(): Sorry not implemented!"); return real_type(); }
00449 real_type diameter() const { assert(false ||!"Ellipsoid::diameter(): Sorry not implemented!"); return real_type(); }
00450
00451 void compute_surface_points(std::vector<vector3_type> & ) const { assert(false ||!"Ellipsoid::compute_surface_points): Sorry not implemented!"); }
00452
00453
00465 void compute_collision_aabb(
00466 vector3_type const & r
00467 , matrix3x3_type const & R
00468 , vector3_type & min_coord
00469 , vector3_type & max_coord
00470 ) const
00471 {
00472
00473 vector3_type ext = vector3_type(this->radius0(), this->radius1(), this->radius2() );
00474 OpenTissue::geometry::compute_obb_aabb(
00475 this->center()
00476 , this->orientation()
00477 , ext
00478 , min_coord
00479 , max_coord
00480 );
00481
00482 }
00483
00484 };
00485
00486 }
00487
00488 }
00489
00490
00491 #endif