Go to the documentation of this file.00001 #ifndef OPENTISSUE_COLLISION_GJK_GJK_SIMPLEX_H
00002 #define OPENTISSUE_COLLISION_GJK_GJK_SIMPLEX_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <stdexcept>
00013
00014 #include <cassert>
00015
00016 namespace OpenTissue
00017 {
00018 namespace gjk
00019 {
00020
00103 template<typename vector3_type>
00104 class Simplex
00105 {
00106 public:
00107
00108 typedef typename vector3_type::value_traits value_traits;
00109 typedef typename vector3_type::value_type real_type;
00110
00111 public:
00112
00113 int m_bitmask;
00114
00115
00116
00117
00118
00119
00120
00121 vector3_type m_v[4];
00122 real_type m_w[4];
00123 vector3_type m_a[4];
00124 vector3_type m_b[4];
00125
00126 public:
00127
00128 Simplex()
00129 : m_bitmask(0)
00130 {
00131 m_v[0].clear();
00132 m_v[1].clear();
00133 m_v[2].clear();
00134 m_v[3].clear();
00135
00136 m_a[0].clear();
00137 m_a[1].clear();
00138 m_a[2].clear();
00139 m_a[3].clear();
00140
00141 m_b[0].clear();
00142 m_b[1].clear();
00143 m_b[2].clear();
00144 m_b[3].clear();
00145
00146 m_w[0] = value_traits::zero();
00147 m_w[1] = value_traits::zero();
00148 m_w[2] = value_traits::zero();
00149 m_w[3] = value_traits::zero();
00150 }
00151
00152 };
00153
00169 template<typename V>
00170 inline bool is_point_in_simplex( V const & p, Simplex<V> const & S)
00171 {
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int used_bit = 1;
00217 for(size_t i = 0u; i < 4u; ++i)
00218 {
00219 if( (S.m_bitmask & used_bit) && (p == S.m_v[i]) )
00220 return true;
00221 used_bit <<= 1;
00222 }
00223 return false;
00224 }
00225
00240 template<typename V>
00241 inline void add_point_to_simplex( V const & p, V const & p_a, V const & p_b , Simplex<V> & S)
00242 {
00243 typedef typename V::value_traits value_traits;
00244
00245 size_t free_idx = 0u;
00246 int free_bit = 1;
00247
00248
00249 while(S.m_bitmask & free_bit)
00250 {
00251 ++free_idx;
00252 free_bit <<= 1;
00253 }
00254
00255 if( free_idx >= 4u )
00256 throw std::logic_error("Simplex did not have any empty entries");
00257
00258 S.m_a[free_idx] = p_a;
00259 S.m_b[free_idx] = p_b;
00260 S.m_v[free_idx] = p;
00261 S.m_w[free_idx] = value_traits::zero();
00262
00263
00264 S.m_bitmask |= free_bit;
00265 }
00266
00275 template<typename V>
00276 inline size_t dimension(Simplex<V> const & S)
00277 {
00278 size_t size = 0u;
00279
00280 if( S.m_bitmask & 1 )
00281 ++size;
00282 if( S.m_bitmask & 2 )
00283 ++size;
00284 if( S.m_bitmask & 4 )
00285 ++size;
00286 if( S.m_bitmask & 8 )
00287 ++size;
00288 return size;
00289 }
00290
00301 template<typename V>
00302 inline bool is_full_simplex(Simplex<V> const & S)
00303 {
00304 return (S.m_bitmask == 15u);
00305 }
00306
00315 inline void get_used_indices( int const & bitmask, size_t & idx_A, int & bit_A)
00316 {
00317 if(bitmask == 0u)
00318 throw std::invalid_argument("no bits was set high in bitmask");
00319
00320 size_t idx = 0u;
00321
00322 bit_A = 1;
00323 for(; idx < 4; ++idx)
00324 {
00325 if( bitmask & bit_A )
00326 break;
00327 bit_A <<= 1;
00328 }
00329 idx_A = idx;
00330
00331 assert( bit_A==1 || bit_A==2 || bit_A==4 || bit_A==8 || !"get_used_indices(): bit A was illegal");
00332 assert( idx_A >= 0u || !"get_used_indices(): illegal index A value");
00333 assert( idx_A < 4u || !"get_used_indices(): illegal index A value");
00334 assert( ((1 << idx_A) & bit_A) || !"get_used_indices(): mismatch between idx A and bit A");
00335 }
00336
00347 inline void get_used_indices(
00348 int const & bitmask
00349 , size_t & idx_A
00350 , int & bit_A
00351 , size_t & idx_B
00352 , int & bit_B
00353 )
00354 {
00355 if(bitmask == 0u)
00356 throw std::invalid_argument("no bits was set high in bitmask");
00357
00358 size_t idx = 0u;
00359
00360 bit_A = 1;
00361 for(; idx < 4u; ++idx)
00362 {
00363 if( bitmask & bit_A )
00364 break;
00365 bit_A <<= 1;
00366 }
00367 idx_A = idx++;
00368
00369 bit_B = bit_A << 1;
00370 for(; idx < 4u; ++idx)
00371 {
00372 if( bitmask & bit_B )
00373 break;
00374 bit_B <<= 1;
00375 }
00376 idx_B = idx;
00377
00378 if(idx_B==4u)
00379 throw std::logic_error("simplex only had one used entry");
00380
00381 assert( bit_A==1 || bit_A==2 || bit_A==4 || bit_A==8 || !"get_used_indices(): bit A was illegal");
00382 assert( idx_A >= 0u || !"get_used_indices(): illegal index A value");
00383 assert( idx_A < 4u || !"get_used_indices(): illegal index A value");
00384 assert( ((1 << idx_A) & bit_A) || !"get_used_indices(): mismatch between idx A and bit A");
00385
00386 assert( bit_B==1 || bit_B==2 || bit_B==4 || bit_B==8 || !"get_used_indices(): bit B was illegal");
00387 assert( idx_B >= 0u || !"get_used_indices(): illegal index B value");
00388 assert( idx_B < 4u || !"get_used_indices(): illegal index B value");
00389 assert( ((1 << idx_B) & bit_B) || !"get_used_indices(): mismatch between idx B and bit B");
00390
00391 assert( ((bit_A & bit_B) == 0) || !"get_used_indices(): Bit A and Bit B was the same");
00392 assert( idx_A < idx_B || !"get_used_indices(): idx A should be smaller than idx B");
00393 }
00394
00407 inline void get_used_indices(
00408 int const & bitmask
00409 , size_t & idx_A
00410 , int & bit_A
00411 , size_t & idx_B
00412 , int & bit_B
00413 , size_t & idx_C
00414 , int & bit_C
00415 )
00416 {
00417 if(bitmask == 0u)
00418 throw std::invalid_argument("no bits was set high in bitmask");
00419
00420 size_t idx = 0u;
00421
00422 bit_A = 1;
00423 for(; idx < 4; ++idx)
00424 {
00425 if( bitmask & bit_A )
00426 break;
00427 bit_A <<= 1;
00428 }
00429 idx_A = idx++;
00430
00431 bit_B = bit_A << 1;
00432 for(; idx < 4; ++idx)
00433 {
00434 if( bitmask & bit_B )
00435 break;
00436 bit_B <<= 1;
00437 }
00438 idx_B = idx++;
00439
00440 if(idx_B==4u)
00441 throw std::logic_error("simplex only had one used entry");
00442
00443 bit_C = bit_B << 1;
00444 for(; idx < 4; ++idx)
00445 {
00446 if( bitmask & bit_C )
00447 break;
00448 bit_C <<= 1;
00449 }
00450 idx_C = idx;
00451
00452 if(idx_C==4u)
00453 throw std::logic_error("simplex only had two used entries");
00454
00455
00456 assert( bit_A==1 || bit_A==2 || bit_A==4 || bit_A==8 || !"get_used_indices(): bit A was illegal");
00457 assert( idx_A >= 0u || !"get_used_indices(): illegal index A value");
00458 assert( idx_A < 4u || !"get_used_indices(): illegal index A value");
00459 assert( ((1 << idx_A) & bit_A) || !"get_used_indices(): mismatch between idx A and bit A");
00460
00461 assert( bit_B==1 || bit_B==2 || bit_B==4 || bit_B==8 || !"get_used_indices(): bit B was illegal");
00462 assert( idx_B >= 0u || !"get_used_indices(): illegal index B value");
00463 assert( idx_B < 4u || !"get_used_indices(): illegal index B value");
00464 assert( ((1 << idx_B) & bit_B) || !"get_used_indices(): mismatch between idx B and bit B");
00465
00466 assert( ((bit_A & bit_B) == 0) || !"get_used_indices(): Bit A and Bit B was the same");
00467 assert( idx_A < idx_B || !"get_used_indices(): idx A should be smaller than idx B");
00468
00469 assert( bit_C==1 || bit_C==2 || bit_C==4 || bit_C==8 || !"get_used_indices(): bit B was illegal");
00470 assert( idx_C >= 0u || !"get_used_indices(): illegal index B value");
00471 assert( idx_C < 4u || !"get_used_indices(): illegal index B value");
00472 assert( ((1 << idx_C) & bit_C) || !"get_used_indices(): mismatch between idx B and bit B");
00473
00474 assert( ((bit_A & bit_C) == 0) || !"get_used_indices(): Bit A and Bit C was the same");
00475 assert( ((bit_B & bit_C) == 0) || !"get_used_indices(): Bit B and Bit C was the same");
00476 assert( idx_B < idx_C || !"get_used_indices(): idx B should be smaller than idx C");
00477
00478 }
00479
00480 }
00481
00482 }
00483
00484
00485 #endif