00001 #ifndef OPENTISSUE_COLLISION_GJK_GJK_H
00002 #define OPENTISSUE_COLLISION_GJK_GJK_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012
00013 #include <OpenTissue/collision/gjk/gjk_compute_closest_points.h>
00014 #include <OpenTissue/collision/gjk/gjk_constants.h>
00015 #include <OpenTissue/collision/gjk/gjk_outside_edge_face_voronoi_plane.h>
00016 #include <OpenTissue/collision/gjk/gjk_outside_triangle.h>
00017 #include <OpenTissue/collision/gjk/gjk_outside_vertex_edge_voronoi_plane.h>
00018 #include <OpenTissue/collision/gjk/gjk_reduce_edge.h>
00019 #include <OpenTissue/collision/gjk/gjk_reduce_tetrahedron.h>
00020 #include <OpenTissue/collision/gjk/gjk_reduce_triangle.h>
00021 #include <OpenTissue/collision/gjk/gjk_signed_distance_to_edge_face_voronoi_plane.h>
00022 #include <OpenTissue/collision/gjk/gjk_signed_distance_to_triangle.h>
00023 #include <OpenTissue/collision/gjk/gjk_signed_distance_to_vertex_edge_voronoi_plane.h>
00024 #include <OpenTissue/collision/gjk/gjk_simplex.h>
00025 #include <OpenTissue/collision/gjk/gjk_support_functors.h>
00026 #include <OpenTissue/collision/gjk/gjk_voronoi_simplex_solver_policy.h>
00027
00028
00029
00030
00031
00032 #include <boost/cast.hpp>
00033
00034 namespace OpenTissue
00035 {
00036 namespace gjk
00037 {
00038 namespace obsolete
00039 {
00040 namespace detail
00041 {
00081 template<typename vector3_type_>
00082 class GJK
00083 {
00084 public:
00085
00086 typedef vector3_type_ vector3_type;
00087 typedef typename vector3_type::value_traits value_traits;
00088 typedef typename vector3_type::value_type real_type;
00089
00090 protected:
00091
00092 real_type m_rel_error;
00093 real_type m_abs_error;
00094 real_type m_abs_error2;
00095
00096 vector3_type m_p[4];
00097 vector3_type m_q[4];
00098 vector3_type m_y[4];
00099
00100 int m_bits;
00101 int m_last;
00102 int m_last_bit;
00103 int m_all_bits;
00104
00105 real_type m_det[16][4];
00106 real_type m_dp[4][4];
00107
00108 public:
00109
00110 GJK()
00111 : m_rel_error( boost::numeric_cast<real_type>(1e-6) )
00112 , m_abs_error( boost::numeric_cast<real_type>(1e-10) )
00113 , m_abs_error2( boost::numeric_cast<real_type>(1e-20) )
00114 {}
00115
00116 public:
00117
00136 template<typename convex_shape_type1, typename convex_shape_type2>
00137 bool is_intersecting(
00138 convex_shape_type1 & A
00139 , convex_shape_type2 & B
00140 , vector3_type & g
00141 )
00142 {
00143 m_bits = 0;
00144 m_all_bits = 0;
00145 do
00146 {
00147
00148
00149
00150 m_last = 0;
00151 m_last_bit = 1;
00152
00153 while(m_bits & m_last_bit)
00154 {
00155 ++m_last;
00156 m_last_bit <<= 1;
00157 }
00158
00159 vector3_type wA = A.get_support_point(-g);
00160 vector3_type wB = B.get_support_point(g);
00161 vector3_type w = wA - wB;
00162
00163
00164 if( g*w > 0)
00165 {
00166 return false;
00167 }
00168 if(this->is_degenerate(w))
00169 {
00170 return false;
00171 }
00172 m_y[m_last] = w;
00173 m_all_bits = m_bits | m_last_bit;
00174 if(!this->get_closest(g))
00175 {
00176 return false;
00177 }
00178
00179
00180
00181
00182
00183
00184 }
00185 while(m_bits < 15 && !this->is_approx_zero(g));
00186
00187 return true;
00188 }
00189
00216 template<typename convex_shape_type1, typename convex_shape_type2>
00217 bool get_common_point(
00218 convex_shape_type1 & A
00219 , convex_shape_type2 & B
00220 , vector3_type & g
00221 , vector3_type & pa
00222 , vector3_type & pb
00223 )
00224 {
00225 m_bits = 0;
00226 m_all_bits = 0;
00227 do
00228 {
00229
00230
00231
00232 m_last = 0;
00233 m_last_bit = 1;
00234 while(m_bits & m_last_bit)
00235 {
00236 ++m_last;
00237 m_last_bit <<= 1;
00238 }
00239
00240 m_p[m_last] = A.get_support_point(-g);
00241 m_q[m_last] = B.get_support_point(g);
00242 vector3_type w = m_p[m_last] - m_q[m_last];
00243 if(g * w > 0)
00244 {
00245 return false;
00246 }
00247 if(this->is_degenerate(w))
00248 {
00249 return false;
00250 }
00251 m_y[m_last] = w;
00252 m_all_bits = m_bits | m_last_bit;
00253 if(!this->get_closest(g))
00254 {
00255 return false;
00256 }
00257
00258
00259
00260
00261
00262 }
00263 while(m_bits<15 && !this->is_approx_zero(g));
00264 this->compute_points(m_bits, pa, pb);
00265 return true;
00266 }
00267
00277 template<typename convex_shape_type1, typename convex_shape_type2>
00278 void get_closest_points(
00279 convex_shape_type1 & A
00280 , convex_shape_type2 & B
00281 , vector3_type & pa
00282 , vector3_type & pb
00283 )
00284 {
00285 using std::max;
00286 using std::sqrt;
00287
00288 vector3_type const zero = vector3_type( value_traits::zero(), value_traits::zero(), value_traits::zero() );
00289
00290 vector3_type vA = A.get_support_point(zero);
00291 vector3_type vB = B.get_support_point(zero);
00292 vector3_type v = vA - vB;
00293
00294 real_type dist = sqrt(v*v);
00295
00296 m_bits = 0;
00297 m_all_bits = 0;
00298 real_type mu = value_traits::zero();
00299
00300
00301
00302
00303
00304
00305 while(m_bits<15 && dist > m_abs_error)
00306 {
00307
00308
00309
00310 m_last = 0;
00311 m_last_bit = 1;
00312
00313 while(m_bits & m_last_bit)
00314 {
00315 ++m_last;
00316 m_last_bit <<= 1;
00317 }
00318
00319 m_p[m_last] = A.get_support_point( - v );
00320 m_q[m_last] = B.get_support_point( v );
00321
00322 vector3_type w = m_p[m_last] - m_q[m_last];
00323
00324 mu = max( mu, ( dot(v,w) / dist) );
00325
00326 if(dist - mu <= dist * m_rel_error)
00327 {
00328 break;
00329 }
00330
00331 if(this->is_degenerate(w))
00332 {
00333 break;
00334 }
00335
00336 m_y[m_last] = w;
00337
00338 m_all_bits = m_bits | m_last_bit;
00339 if(!this->get_closest(v))
00340 {
00341 break;
00342 }
00343 dist = sqrt( dot(v,v) );
00344 }
00345 this->compute_points(m_bits, pa, pb);
00346 }
00347
00348 private:
00349
00360 bool is_approx_zero(vector3_type & vec)
00361 {
00362 return (vec*vec < m_abs_error2);
00363 }
00364
00370 void compute_determinants()
00371 {
00372
00373
00374
00375
00376 for(int i=0, bit=1; i<4; ++i, bit <<=1)
00377 {
00378
00379 if(m_bits & bit)
00380 {
00381 m_dp[i][m_last] = m_dp[m_last][i] = m_y[i] * m_y[m_last];
00382 }
00383 }
00384 m_dp[m_last][m_last] = m_y[m_last] * m_y[m_last];
00385
00386
00387
00388
00389
00390
00391
00392 m_det[m_last_bit][m_last] = value_traits::one();
00393
00394
00395
00396
00397
00398 for(int j=0, sj=1; j<4; ++j, sj <<= 1)
00399 {
00400 if(m_bits & sj)
00401 {
00402 int s2 = sj | m_last_bit;
00403 m_det[s2][j] = m_dp[m_last][m_last] - m_dp[m_last][j];
00404 m_det[s2][m_last] = m_dp[j][j] - m_dp[j][m_last];
00405 for(int k=0, sk=1; k<j; ++k, sk <<= 1)
00406 {
00407 if(m_bits & sk)
00408 {
00409 int s3 = sk | s2;
00410 m_det[s3][k] = m_det[s2][j] * (m_dp[j][j] - m_dp[j][k] ) + m_det[s2][m_last] * (m_dp[m_last][j] - m_dp[m_last][k]);
00411 m_det[s3][j] = m_det[sk | m_last_bit][k] * (m_dp[k][k] - m_dp[k][j] ) + m_det[sk | m_last_bit][m_last] * (m_dp[m_last][k] - m_dp[m_last][j]);
00412 m_det[s3][m_last] = m_det[sk|sj][k] * (m_dp[k][k] - m_dp[k][m_last]) + m_det[sk | sj][j] * (m_dp[j][k] - m_dp[j][m_last]);
00413 }
00414 }
00415 }
00416 }
00417
00418
00419
00420
00421
00422 if(m_all_bits == 15)
00423 {
00424
00425 m_det[15][0] = m_det[14][1] * (m_dp[1][1] - m_dp[1][0]) + m_det[14][2] * (m_dp[2][1] - m_dp[2][0]) + m_det[14][3] * (m_dp[3][1] - m_dp[3][0]);
00426
00427 m_det[15][1] = m_det[13][0] * (m_dp[0][0] - m_dp[0][1]) + m_det[13][2] * (m_dp[2][0] - m_dp[2][1]) + m_det[13][3] * (m_dp[3][0] - m_dp[3][1]);
00428
00429 m_det[15][2] = m_det[11][0] * (m_dp[0][0] - m_dp[0][2]) + m_det[11][1] * (m_dp[1][0] - m_dp[1][2]) + m_det[11][3] * (m_dp[3][0] - m_dp[3][2]);
00430
00431 m_det[15][3] = m_det[7][0] * (m_dp[0][0] - m_dp[0][3]) + m_det[7][1] * (m_dp[1][0] - m_dp[1][3]) + m_det[7][2] * (m_dp[2][0] - m_dp[2][3]);
00432 }
00433 }
00434
00445 bool is_valid(int s)
00446 {
00447 for(int i=0, bit=1; i<4; ++i, bit <<= 1)
00448 {
00449
00450
00451 if(m_all_bits & bit)
00452 {
00453
00454 if(s & bit)
00455 {
00456
00457 if(m_det[s][i]<=0)
00458 {
00459 return false;
00460 }
00461 }
00462 else if(m_det[ (s|bit) ][i] > 0)
00463 {
00464
00465 return false;
00466 }
00467 }
00468 }
00469
00470
00471
00472 return true;
00473 }
00474
00491 void compute_vector(int new_bits, vector3_type & vec)
00492 {
00493 real_type sum = value_traits::zero();
00494 vec.clear();
00495 for(int i=0, bit=1; i<4; ++i, bit <<= 1)
00496 {
00497
00498 if(new_bits & bit)
00499 {
00500 sum += m_det[new_bits][i];
00501 vec += m_y[i] * m_det[new_bits][i];
00502 }
00503 }
00504 vec *= value_traits::one()/sum;
00505 }
00506
00522 void compute_points(int new_bits, vector3_type & p1, vector3_type & p2)
00523 {
00524 real_type sum = value_traits::zero();
00525 p1.clear();
00526 p2.clear();
00527 for (int i=0, bit=1; i<4; ++i, bit <<= 1)
00528 {
00529 if(new_bits & bit)
00530 {
00531 sum += m_det[new_bits][i];
00532 p1 += m_p[i]*m_det[new_bits][i];
00533 p2 += m_q[i]*m_det[new_bits][i];
00534 }
00535 }
00536 if(sum)
00537 {
00538 real_type s = value_traits::one() / sum;
00539 p1 *= s;
00540 p2 *= s;
00541 }
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00580 bool get_closest(vector3_type & vec)
00581 {
00582
00583 this->compute_determinants();
00584
00585
00586 for(int s=m_bits; s; --s)
00587 {
00588
00589
00590 if((s & m_bits) == s)
00591 {
00592
00593
00594 if( this->is_valid( s | m_last_bit) )
00595 {
00596
00597
00598 m_bits = s | m_last_bit;
00599
00600
00601
00602
00603 this->compute_vector(m_bits, vec);
00604 return true;
00605 }
00606 }
00607 }
00608
00609
00610
00611
00612 if(this->is_valid(m_last_bit))
00613 {
00614 m_bits = m_last_bit;
00615 vec = m_y[m_last];
00616 return true;
00617 }
00618 return false;
00619 }
00620
00621
00632 bool is_degenerate(vector3_type & vec)
00633 {
00634 for(int i=0, bit=1; i<4; ++i, bit <<= 1)
00635 {
00636 if((m_all_bits & bit) && m_y[i]==vec)
00637 return true;
00638 }
00639 return false;
00640 }
00641
00642 };
00643
00644 }
00645
00664 template< typename convex_shape_type1, typename convex_shape_type2, typename vector3_type >
00665 bool is_intersecting(convex_shape_type1 & A,convex_shape_type2 & B,vector3_type & g)
00666 {
00667 OpenTissue::gjk::obsolete::detail::GJK<vector3_type> algorithm;
00668 return algorithm.is_intersecting( A, B, g);
00669 }
00670
00697 template< typename convex_shape_type1, typename convex_shape_type2, typename vector3_type>
00698 bool get_common_point(convex_shape_type1 & A, convex_shape_type2 & B, vector3_type & g, vector3_type & pa, vector3_type & pb)
00699 {
00700 OpenTissue::gjk::obsolete::detail::GJK<vector3_type> algorithm;
00701 return algorithm.get_common_point( A, B, g, pa, pb);
00702 }
00703
00713 template< typename convex_shape_type1, typename convex_shape_type2, typename vector3_type>
00714 void get_closest_points(convex_shape_type1 & A, convex_shape_type2 & B, vector3_type & pa, vector3_type & pb)
00715 {
00716 OpenTissue::gjk::obsolete::detail::GJK<vector3_type> algorithm;
00717 algorithm.get_closest_points( A, B, pa, pb);
00718 }
00719
00720 }
00721 }
00722 }
00723
00724
00725 #endif