00001 #ifndef OPENTISSUE_DYNAMICS_SPH_COLLISION_POLICIES_SPH_IMPLICIT_PRIMITIVES_POINTS_H
00002 #define OPENTISSUE_DYNAMICS_SPH_COLLISION_POLICIES_SPH_IMPLICIT_PRIMITIVES_POINTS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/sph/collision/sph_collision_type.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014 #include <OpenTissue/core/math/math_functions.h>
00015
00016 #include <map>
00017
00018
00019 namespace OpenTissue
00020 {
00021 namespace sph
00022 {
00023
00024 template <
00025 typename real_type_
00026 , typename vector_type
00027 >
00028 class ImplicitPrimitive
00029 {
00030 public:
00031 typedef real_type_ real_type;
00032 typedef vector_type vector;
00033
00034 public:
00035 virtual ~ImplicitPrimitive()
00036 {}
00037
00038 public:
00039 virtual real_type F(const vector& p) const = 0;
00040
00041 virtual void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const = 0;
00042
00043 };
00044
00045
00046 template <
00047 typename real_type_
00048 , typename vector_type
00049 , typename sphere_type
00050 >
00051 class ImplicitSpherePrimitive : public ImplicitPrimitive<real_type_, vector_type>
00052 {
00053 public:
00054
00055 typedef ImplicitPrimitive<real_type_, vector_type> base_type;
00056 typedef real_type_ real_type;
00057 typedef typename base_type::vector vector;
00058 typedef sphere_type sphere;
00059
00060 public:
00061 ImplicitSpherePrimitive(const sphere& sphere)
00062 : base_type()
00063 , m_sphere(sphere)
00064 {}
00065
00066 ~ImplicitSpherePrimitive()
00067 {}
00068
00069 public:
00070 real_type F(const vector& p) const
00071 {
00072 const vector tmp = p-m_sphere.center();
00073 return tmp*tmp - m_sphere.squared_radius();
00074 }
00075
00076 void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const
00077 {
00078 const vector tmp = p-m_sphere.center();
00079 const real_type depth = length(tmp)-m_sphere.radius();
00080 d = std::fabs(depth);
00081 n = normalize(tmp);
00082 cp = m_sphere.center()+n*m_sphere.radius();
00083
00084 n *= math::sgn(depth);
00085 }
00086
00087 private:
00088 ImplicitSpherePrimitive& operator=(const ImplicitSpherePrimitive& rhs)
00089 {
00090 }
00091
00092 private:
00093 const sphere& m_sphere;
00094
00095 };
00096
00097
00098 template <
00099 typename real_type_
00100 , typename vector_type
00101 , typename capsule_type
00102 >
00103 class ImplicitCapsulePrimitive : public ImplicitPrimitive<real_type_, vector_type>
00104 {
00105 public:
00106 typedef ImplicitPrimitive<real_type_, vector_type> base_type;
00107 typedef real_type_ real_type;
00108 typedef typename base_type::vector vector;
00109 typedef capsule_type capsule;
00110
00111 public:
00112 ImplicitCapsulePrimitive(const capsule& capsule) : base_type()
00113 , m_capsule(capsule)
00114 {}
00115
00116 ~ImplicitCapsulePrimitive()
00117 {}
00118
00119 public:
00120 real_type F(const vector& p) const
00121 {
00122 return m_capsule.evaluate(p);
00123 }
00124
00125 void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const
00126 {
00127 using std::fabs;
00128 d = fabs(m_capsule.signed_distance(p));
00129 n = m_capsule.normal(p);
00130 cp = m_capsule.closest_point_on_line_segment(p)+n*m_capsule.radius();
00131 }
00132
00133 private:
00134 ImplicitCapsulePrimitive& operator=(const ImplicitCapsulePrimitive& rhs)
00135 {
00136 }
00137
00138 private:
00139 const capsule& m_capsule;
00140
00141 };
00142
00143
00144 template <
00145 typename real_type_
00146 , typename vector_type
00147 >
00148 class ImplicitPlanePrimitive : public ImplicitPrimitive<real_type_, vector_type>
00149 {
00150 public:
00151 typedef ImplicitPrimitive<real_type_, vector_type> base_type;
00152 typedef real_type_ real_type;
00153 typedef typename base_type::vector vector;
00154
00155 public:
00156 ImplicitPlanePrimitive(const vector& x0 = 0, const vector& n = 0) : base_type()
00157 , m_x0(x0)
00158 , m_n(n)
00159 {}
00160
00161 ~ImplicitPlanePrimitive()
00162 {}
00163
00164 public:
00165
00166 const vector& point() const
00167 {
00168 return m_x0;
00169 }
00170
00171 vector& point()
00172 {
00173 return m_x0;
00174 }
00175
00176 const vector& normal() const
00177 {
00178 return m_n;
00179 }
00180
00181 vector& normal()
00182 {
00183 return m_n;
00184 }
00185
00186 public:
00187 real_type F(const vector& p) const
00188 {
00189 return m_n*(p-m_x0);
00190 }
00191
00192 void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const
00193 {
00194 const vector tmp = p-m_x0;
00195 n = normalize(m_n);
00196 d = std::fabs(tmp*n);
00197 cp = p+n*d;
00198 }
00199
00200 private:
00201 vector m_x0;
00202 vector m_n;
00203
00204 };
00205
00206 #if 1
00207 template <
00208 typename real_type_
00209 , typename vector_type
00210 , typename box_type
00211 >
00212 class ImplicitBoxPrimitive : public ImplicitPrimitive<real_type_, vector_type>
00213 {
00214 public:
00215 typedef ImplicitPrimitive<real_type_, vector_type> base_type;
00216 typedef real_type_ real_type;
00217 typedef typename base_type::vector vector;
00218 typedef box_type box;
00219
00220 public:
00221 ImplicitBoxPrimitive(const box& box) : base_type()
00222 , m_box(box)
00223 {}
00224
00225 ~ImplicitBoxPrimitive()
00226 {}
00227
00228 public:
00229
00230 real_type F(const vector& p) const
00231 {
00232 const vector p_local = trans(m_box.orientation())*(p-m_box.center());
00233 const vector tmp = fabs(p_local)-m_box.ext();
00234 const real_type res = max_value(tmp);
00235
00236 return res;
00237 }
00238
00239 void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const
00240 {
00241 const vector c = m_box.center();
00242 typename box::matrix3x3_type const& R = m_box.orientation();
00243 typename box::matrix3x3_type const Rt = trans(R);
00244 const vector& x = m_box.ext();
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 int coli = 0;
00262 cp = Rt*(p-c);
00263 n = vector(0);
00264 if (cp(0) > x(0)) {
00265 cp(0) = x(0);
00266 n -= Rt[0];
00267 coli++;
00268 }
00269 else if (cp(0) < -x(0)) {
00270 cp(0) = -x(0);
00271 n += Rt[0];
00272 coli++;
00273 }
00274
00275 if (cp(1) > x(1)) {
00276 cp(1) = x(1);
00277 n -= Rt[1];
00278 coli++;
00279 }
00280 else if (cp(1) < -x(1)) {
00281 cp(1) = -x(1);
00282 n += Rt[1];
00283 coli++;
00284 }
00285
00286 if (cp(2) > x(2)) {
00287 cp(2) = x(2);
00288 n -= Rt[2];
00289 coli++;
00290 }
00291 else if (cp(2) < -x(2)) {
00292 cp(2) = -x(2);
00293 n += Rt[2];
00294 coli++;
00295 }
00296
00297 cp = c + R*cp;
00298 d = length(cp-p);
00299 n = unit(n);
00300
00301
00302
00303 if (coli > 1) {
00304 vector disp;
00305 random(disp, 0, 0.0001);
00306 disp(0) *= n(0);
00307 disp(1) *= n(1);
00308 disp(2) *= n(2);
00309 cp += disp;
00310 }
00311
00312
00313
00314
00315
00316
00317 }
00318
00319 private:
00320 ImplicitBoxPrimitive& operator=(const ImplicitBoxPrimitive& rhs)
00321 {}
00322
00323 private:
00324 const box& m_box;
00325
00326 };
00327 #else
00328 template <
00329 typename real_type_
00330 , typename vector_type
00331 >
00332 class ImplicitBoxPrimitive : public ImplicitPrimitive<real_type_, vector_type>
00333 {
00334 public:
00335 typedef ImplicitPrimitive<real_type_, vector_type> base_type;
00336 typedef ImplicitPlanePrimitive<real_type_, vector_type> plane;
00337 typedef real_type_ real_type;
00338 typedef typename base_type::vector vector;
00339
00340 public:
00341 ImplicitBoxPrimitive(const vector& pMin = 0, const vector& pMax = 0)
00342 : m_pMin(pMin)
00343 , m_pMax(pMax)
00344 {
00345 setBox();
00346 }
00347
00348 public:
00349
00350 void setBox()
00351 {
00352 const vector center = m_pMin+0.5*(m_pMax-m_pMin);
00353
00354 m_p[0].point() = vector(m_pMin[0], center[1], center[2]);
00355 m_p[0].normal() = vector(1., 0., 0.);
00356
00357 m_p[1].point() = vector(m_pMax[0], center[1], center[2]);
00358 m_p[1].normal() = vector(-1., 0., 0.);
00359
00360 m_p[2].point() = vector(center[0], m_pMin[1], center[2]);
00361 m_p[2].normal() = vector(0., 1., 0.);
00362
00363 m_p[3].point() = vector(center[0], m_pMax[1], center[2]);
00364 m_p[3].normal() = vector(0., -1., 0.);
00365
00366 m_p[4].point() = vector(center[0], center[1], m_pMin[2]);
00367 m_p[4].normal() = vector(0., 0., 1.);
00368
00369 m_p[5].point() = vector(center[0], center[1], m_pMax[2]);
00370 m_p[5].normal() = vector(0., 0., -1.);
00371 }
00372
00373 const vector& min_point() const
00374 {
00375 return m_pMin;
00376 }
00377
00378 vector& min_point()
00379 {
00380 return m_pMin;
00381 }
00382
00383 const vector& max_point() const
00384 {
00385 return m_pMax;
00386 }
00387
00388 vector& max_point()
00389 {
00390 return m_pMax;
00391 }
00392
00393 public:
00394 real_type F(const vector& p) const
00395 {
00396 using std::min;
00397
00398 real_type res = math::detail::highest<real_type>();
00399 for (int n = 0; n < 6; ++n)
00400 res = min(res, m_p[n].F(p));
00401 return res;
00402 }
00403
00404 void collisionInfo(vector& cp, vector& n, real_type& d, const vector& p) const
00405 {
00406 n = 0.;
00407 for (int i = 0; i < 6; ++i)
00408 if (m_p[i].F(p) < 0.)
00409 n += m_p[i].normal();
00410 cp = p;
00411
00412 if (n[0] > 0.)
00413 cp[0] = m_pMin[0];
00414 else if (n[0] < 0.)
00415 cp[0] = m_pMax[0];
00416
00417 if (n[1] > 0.)
00418 cp[1] = m_pMin[1];
00419 else if (n[1] < 0.)
00420 cp[1] = m_pMax[1];
00421
00422 if (n[2] > 0.)
00423 cp[2] = m_pMin[2];
00424 else if (n[2] < 0.)
00425 cp[2] = m_pMax[2];
00426
00427 n = unit(n);
00428 d = length(cp-p);
00429 }
00430
00431 private:
00432 vector m_pMin;
00433 vector m_pMax;
00434 plane m_p[6];
00435
00436 };
00437 #endif
00438
00439 template <
00440 typename real_type_
00441 , typename vector_type
00442 , typename point_data_type
00443 >
00444 class ImplicitPrimitivesCollisionDetectionPolicy
00445 {
00446 public:
00447 typedef real_type_ real_type;
00448 typedef vector_type vector;
00449 typedef point_data_type point_data;
00450 typedef enum {CONTAINER, OBSTACLE} primitive_type;
00451 typedef CollisionType<real_type, vector> collision_type;
00452 typedef ImplicitPrimitive<real_type, vector_type> implicit_primitive;
00453 typedef std::map<const implicit_primitive*, primitive_type> implicit_primitives;
00454
00455 public:
00456
00457 void clear()
00458 {
00459 m_primitives.clear();
00460 }
00461
00462 template< typename implicit_ptimitive >
00463 void addObstacle(const implicit_ptimitive& obstacle)
00464 {
00465 m_primitives[&obstacle] = OBSTACLE;
00466 }
00467
00468 template< typename implicit_ptimitive >
00469 void addContainer(const implicit_ptimitive& container)
00470 {
00471 m_primitives[&container] = CONTAINER;
00472 }
00473
00474 void refresh()
00475 {
00476 }
00477
00478 bool collision(collision_type& collision, const point_data& query)
00479 {
00480 typename implicit_primitives::const_iterator end = m_primitives.end();
00481 for (typename implicit_primitives::const_iterator ips = m_primitives.begin(); ips != end; ++ips) {
00482 const implicit_primitive* ip = ips->first;
00483 const real_type val = ip->F(query.position());
00484 if ((CONTAINER == ips->second && val > 0.) ||
00485 (OBSTACLE == ips->second && val < 0.))
00486 {
00487 ip->collisionInfo(collision.contact(), collision.normal(), collision.penetration(), query.position());
00488 return true;
00489 }
00490 }
00491 return false;
00492 }
00493
00494 protected:
00495
00496 implicit_primitives m_primitives;
00497
00498 };
00499
00500 }
00501 }
00502
00503
00504 #endif