00001 #ifndef OPENTISSUE_DYNAMICS_SPH_COLLISION_POLICIES_SPH_TETRAHEDRA_POINTS_H
00002 #define OPENTISSUE_DYNAMICS_SPH_COLLISION_POLICIES_SPH_TETRAHEDRA_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/collision/spatial_hashing/spatial_hashing.h>
00014 #include <OpenTissue/core/geometry/geometry_triangle.h>
00015 #include <OpenTissue/core/geometry/geometry_plane.h>
00016 #include <OpenTissue/core/math/math_basic_types.h>
00017
00018 #include <vector>
00019
00020
00021 namespace OpenTissue
00022 {
00023 namespace sph
00024 {
00025
00026 template <
00027 typename real_type_
00028 , typename vector3_type_
00029 , typename tetrahedron_type_
00030 , typename point_data_type
00031 >
00032 class TetrahedraPointsCollisionDetectionPolicy
00033 {
00034 public:
00035 typedef math::BasicMathTypes<real_type_, int> math_types;
00036 typedef real_type_ real_type;
00037 typedef vector3_type_ vector3_type;
00038 typedef tetrahedron_type_ tetrahedron_type;
00039 typedef point_data_type point_data;
00040 typedef CollisionType<real_type, vector3_type> collision_type;
00041 typedef std::vector<collision_type> collision_container;
00042
00043 public:
00044
00054 class TetrahedronWrapper
00055 {
00056 public:
00057 typedef tetrahedron_type tetrahedron_type_inner;
00058 typedef typename tetrahedron_type_inner::node_type node_type;
00059 typedef typename node_type::point_type point_type;
00060
00061 public:
00062 TetrahedronWrapper(const tetrahedron_type_inner* tetrahedron)
00063 : m_tetrahedron(tetrahedron)
00064
00065 {}
00066
00067 public:
00068
00069 const tetrahedron_type_inner* data() const
00070 {
00071 return m_tetrahedron;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 point_type min() const
00083 {
00084 using std::min;
00085
00086 const point_type& p0 = m_tetrahedron->i()->vertex();
00087 const point_type& p1 = m_tetrahedron->j()->vertex();
00088 const point_type& p2 = m_tetrahedron->k()->vertex();
00089 const point_type& p3 = m_tetrahedron->m()->vertex();
00090 return min(p0, min(p1, min(p2, p3)));
00091 }
00092
00093 point_type max() const
00094 {
00095 using std::max;
00096
00097 const point_type& p0 = m_tetrahedron->i()->vertex();
00098 const point_type& p1 = m_tetrahedron->j()->vertex();
00099 const point_type& p2 = m_tetrahedron->k()->vertex();
00100 const point_type& p3 = m_tetrahedron->m()->vertex();
00101 return max(p0, max(p1, max(p2, p3)));
00102 }
00103
00104 public:
00105 const tetrahedron_type_inner* m_tetrahedron;
00106
00107
00108 };
00109
00110
00120 class PointWrapper
00121 {
00122 public:
00123 typedef point_data point_data_inner;
00124 typedef typename point_data_inner::point_type point_type;
00125
00126 public:
00127 PointWrapper(const point_data_inner* point)
00128 : m_point(point)
00129 {}
00130
00131 public:
00132 const point_data_inner* data() const
00133 {
00134 return m_point;
00135 }
00136
00137 const point_type& position() const
00138 {
00139 return m_point->position();
00140 }
00141
00142 const point_type& min() const
00143 {
00144 return m_point->position();
00145 }
00146
00147 const point_type& max() const
00148 {
00149 return m_point->position();
00150 }
00151
00152 private:
00153 const point_data_inner* m_point;
00154
00155 };
00156
00157 public:
00158 typedef TetrahedronWrapper tetrahedron_wrapper;
00159 typedef typename tetrahedron_wrapper::tetrahedron_type_inner tetrahedron;
00160 typedef PointWrapper point_wrapper;
00161 typedef std::vector<tetrahedron_wrapper> tetrahedron_container;
00162 typedef typename tetrahedron_container::iterator tetrahedron_iterator;
00163 typedef geometry::Triangle<math_types> Triangle;
00164 typedef geometry::Plane<math_types> Plane;
00165
00166 public:
00167
00168 class CollisionPolicy
00169 {
00170 public:
00171 typedef typename math_types::real_type real_type;
00172 typedef typename math_types::vector3_type vector_inner;
00173 typedef typename tetrahedron_wrapper::point_type t_point_type;
00174 typedef typename point_wrapper::point_type p_point_type;
00175 typedef tetrahedron_wrapper data_type;
00176 typedef point_wrapper query_type;
00177
00178 typedef OpenTissue::spatial_hashing::PrimeNumberHashFunction hash_function;
00179 typedef OpenTissue::spatial_hashing::Grid<vector_inner, OpenTissue::math::Vector3<long>, data_type, hash_function> hash_grid;
00180
00181 public:
00182
00183 struct ResultType
00184 {
00185 const point_data* point;
00186 const tetrahedron_type* tetrahedron;
00187 real_type w0, w1, w2, w3;
00188 };
00189
00190 typedef ResultType result_type;
00191 typedef std::vector<result_type> result_container;
00192
00193 public:
00194
00195 point_data min_coord(data_type const & d)const{return d.min();};
00196 point_data max_coord(data_type const & d)const{return d.max();};
00197 point_data min_coord(query_type const & q)const{return q.min();};
00198 point_data max_coord(query_type const & q)const{return q.max();};
00199
00200 void reset(result_container& results)
00201 {
00202 results.clear();
00203 }
00204
00205 void report(data_type& data, const query_type& query, result_container& results)
00206 {
00207
00208
00209
00210
00211 const tetrahedron_type* t = data.data();
00212 const t_point_type& pi = t->i()->vertex();
00213 const t_point_type& pj = t->j()->vertex();
00214 const t_point_type& pk = t->k()->vertex();
00215 const t_point_type& pm = t->m()->vertex();
00216 const p_point_type& p = query.position();
00217
00218 result_type result;
00219
00220 OpenTissue::geometry::barycentric_algebraic(pi, pj, pk, pm, p, result.w0, result.w1, result.w2, result.w3);
00221
00222
00223
00224
00225
00226
00227 if (result.w0 >= 0 &&
00228 result.w1 >= 0 &&
00229 result.w2 >= 0 &&
00230 result.w3 >= 0)
00231 {
00232
00233 result.point = query.data();
00234 result.tetrahedron = data.data();
00235 results.push_back(result);
00236 }
00237 }
00238
00239 };
00240
00241 public:
00242 typedef CollisionPolicy collision_policy;
00243 typedef typename collision_policy::t_point_type t_point_type;
00244 typedef typename collision_policy::p_point_type p_point_type;
00245 typedef typename collision_policy::result_type result_type;
00246 typedef typename collision_policy::result_container result_container;
00247
00248 typedef OpenTissue::spatial_hashing::AABBDataQuery<typename collision_policy::hash_grid, collision_policy> collision_detection;
00249
00250 public:
00251
00252 void clear()
00253 {
00254 m_tetrahedra.clear();
00255 }
00256
00257 template< typename TetrahedronIterator >
00258 void addObstacle(const TetrahedronIterator& begin, const TetrahedronIterator& end)
00259 {
00260 for (TetrahedronIterator t = begin; t != end; ++t)
00261 m_tetrahedra.push_back(tetrahedron_wrapper(&*t));
00262
00263 refresh();
00264 }
00265
00266 void refresh()
00267 {
00268 m_collision.init(m_tetrahedra.begin(), m_tetrahedra.end());
00269 m_collision(m_tetrahedra.begin(), m_tetrahedra.end());
00270 }
00271
00272 bool collision(collision_type& collision, const point_data& query)
00273 {
00274 point_wrapper q(&query);
00275 result_container collisions;
00276
00277
00278
00279
00280
00281 m_collision(q, collisions, typename collision_detection::all_tag());
00282 if (collisions.empty())
00283 return false;
00284
00285 static int miss = 0;
00286 typename result_container::const_iterator end = collisions.end();
00287 for (typename result_container::const_iterator c = collisions.begin(); c != end; ++c) {
00288 const result_type& coli = *c;
00289
00290 const p_point_type& p0 = coli.point->position_old();
00291 const p_point_type& p1 = coli.point->position();
00292 const p_point_type dir = p0-p1;
00293
00294
00295 const t_point_type& i = coli.tetrahedron->i()->vertex();
00296 const t_point_type& j = coli.tetrahedron->j()->vertex();
00297 const t_point_type& k = coli.tetrahedron->k()->vertex();
00298 const t_point_type& m = coli.tetrahedron->m()->vertex();
00299
00300
00301 dcoli.t4 = c->tetrahedron;
00302 dcoli.p0 = p0; dcoli.p1 = p1;
00303 dcoli.i = i; dcoli.j = j; dcoli.k = k; dcoli.m = m;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 if (intersectTriangleLine(collision, p0+dir, p1, Triangle(j, k, m)))
00318 return true;
00319 if (intersectTriangleLine(collision, p0+dir, p1, Triangle(i, j, m)))
00320 return true;
00321 if (intersectTriangleLine(collision, p0+dir, p1, Triangle(k, i, m)))
00322 return true;
00323 if (intersectTriangleLine(collision, p0+dir, p1, Triangle(i, k, j)))
00324 return true;
00325
00326 }
00327
00328
00329 std::cout << "MISS: " << ++miss << std::endl;
00330 collision.contact() = 0;
00331 return true;
00332 }
00333
00334 bool intersectTriangleLine(collision_type& collision, const p_point_type& p0, const p_point_type& p1, const Triangle& t) const
00335 {
00336 Plane plane(t.p0(), t.p1(), t.p2());
00337 real_type dist_p0 = plane.signed_distance(p0);
00338 real_type dist_p1 = plane.signed_distance(p1);
00339 if (dist_p0 >= 0. && dist_p1 >= 0.)
00340 return false;
00341 if (dist_p0 < 0. && dist_p1 < 0.)
00342 return false;
00343 double const s = dist_p0/(dist_p0-dist_p1);
00344 p_point_type const u = p0 + s*(p1-p0);
00345 real_type w1, w2, w3;
00346 t.barycentric(u, w1, w2, w3);
00347 if (w1 < 0. || w2 < 0. || w3 < 0.)
00348 return false;
00349
00350 collision.contact() = u;
00351 collision.normal() = t.normal();
00352 collision.penetration() = length(u-p1);
00353
00354 return true;
00355 }
00356
00357 public:
00358 struct ColiDebug {
00359 ColiDebug():t4(NULL){}
00360 const tetrahedron_type* t4;
00361 p_point_type p0, p1;
00362 t_point_type i, j, k, m;
00363 } dcoli;
00364
00365 protected:
00366 tetrahedron_container m_tetrahedra;
00367 collision_detection m_collision;
00368
00369 };
00370
00371 }
00372 }
00373
00374
00375 #endif