00001 #ifndef OPENTISSUE_COLLISION_COLLISION_BOX_BOX_IMPROVED_H
00002 #define OPENTISSUE_COLLISION_COLLISION_BOX_BOX_IMPROVED_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_coordsys.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014
00015 #include <OpenTissue/core/math/math_precision.h>
00016 #include <OpenTissue/core/geometry/geometry_compute_closest_points_line_line.h>
00017 #include <OpenTissue/collision/intersect/intersect_rect_quad_edges.h>
00018
00019 namespace OpenTissue
00020 {
00021 namespace collision
00022 {
00023
00040 template<typename real_type,typename vector3_type,typename matrix3x3_type>
00041 unsigned int box_box_improved(
00042 vector3_type p_a
00043 , matrix3x3_type R_a
00044 , vector3_type const & ext_a
00045 , vector3_type p_b
00046 , matrix3x3_type R_b
00047 , vector3_type const & ext_b
00048 , real_type const & envelope
00049 , vector3_type * p
00050 , vector3_type & n
00051 , real_type * distances
00052 )
00053 {
00054 using std::fabs;
00055 using std::min;
00056 using std::max;
00057 using std::sqrt;
00058
00059 typedef math::CoordSys<real_type> coordsys_type;
00060 typedef typename coordsys_type::quaternion_type quaternion_type;
00061
00062 assert(p);
00063 assert(distances);
00064
00065
00066 vector3_type sign[8];
00067 for(unsigned int mask=0;mask<8;++mask)
00068 {
00069 sign[mask](0) = (mask&0x0001)?1:-1;
00070 sign[mask](1) = ((mask>>1)&0x0001)?1:-1;
00071 sign[mask](2) = ((mask>>2)&0x0001)?1:-1;
00072 }
00073
00074 vector3_type A[3];
00075 A[0](0) = R_a(0,0); A[0](1) = R_a(1,0); A[0](2) = R_a(2,0);
00076 A[1](0) = R_a(0,1); A[1](1) = R_a(1,1); A[1](2) = R_a(2,1);
00077 A[2](0) = R_a(0,2); A[2](1) = R_a(1,2); A[2](2) = R_a(2,2);
00078
00079 vector3_type B[3];
00080 B[0](0) = R_b(0,0); B[0](1) = R_b(1,0); B[0](2) = R_b(2,0);
00081 B[1](0) = R_b(0,1); B[1](1) = R_b(1,1); B[1](2) = R_b(2,1);
00082 B[2](0) = R_b(0,2); B[2](1) = R_b(1,2); B[2](2) = R_b(2,2);
00083
00084
00085
00086
00087
00088 for(unsigned int i=0;i<3;++i)
00089 for(unsigned int j=0;j<3;++j)
00090 {
00091 if( fabs( A[i](j) ) < 10e-7 )
00092 A[i](j) = 0.;
00093 if( fabs( B[i](j) ) < 10e-7 )
00094 B[i](j) = 0.;
00095 }
00096
00097 vector3_type a[8];
00098 vector3_type b[8];
00099
00100 for(unsigned int i=0;i<8;++i)
00101 {
00102 a[i] = sign[i](2)*A[2]*ext_a(2) + sign[i](1)*A[1]*ext_a(1) + sign[i](0)*A[0]*ext_a(0) + p_a;
00103 b[i] = sign[i](2)*B[2]*ext_b(2) + sign[i](1)*B[1]*ext_b(1) + sign[i](0)*B[0]*ext_b(0) + p_b;
00104 }
00105
00106
00107 vector3_type axis[15];
00108 axis[0] = A[0];
00109 axis[1] = A[1];
00110 axis[2] = A[2];
00111 axis[3] = B[0];
00112 axis[4] = B[1];
00113 axis[5] = B[2];
00114 axis[6] = A[0] % B[0];
00115 if(axis[6](0)==0 && axis[6](1)==0 && axis[6](2)==0)
00116 axis[6] = A[0];
00117 else
00118 axis[6] /= sqrt(axis[6]*axis[6]);
00119 axis[7] = A[0] % B[1];
00120 if(axis[7](0)==0 && axis[7](1)==0 && axis[7](2)==0)
00121 axis[7] = A[0];
00122 else
00123 axis[7] /= sqrt(axis[7]*axis[7]);
00124 axis[8] = A[0] % B[2];
00125 if(axis[8](0)==0 && axis[8](1)==0 && axis[8](2)==0)
00126 axis[8] = A[0];
00127 else
00128 axis[8] /= sqrt(axis[8]*axis[8]);
00129 axis[9] = A[1] % B[0];
00130 if(axis[9](0)==0 && axis[9](1)==0 && axis[9](2)==0)
00131 axis[9] = A[1];
00132 else
00133 axis[9] /= sqrt(axis[9]*axis[9]);
00134 axis[10] = A[1] % B[1];
00135 if(axis[10](0)==0 && axis[10](1)==0 && axis[10](2)==0)
00136 axis[10] = A[1];
00137 else
00138 axis[10] /= sqrt(axis[10]*axis[10]);
00139 axis[11] = A[1] % B[2];
00140 if(axis[11](0)==0 && axis[11](1)==0 && axis[11](2)==0)
00141 axis[11] = A[1];
00142 else
00143 axis[11] /= sqrt(axis[11]*axis[11]);
00144 axis[12] = A[2] % B[0];
00145 if(axis[12](0)==0 && axis[12](1)==0 && axis[12](2)==0)
00146 axis[12] = A[2];
00147 else
00148 axis[12] /= sqrt(axis[12]*axis[12]);
00149 axis[13] = A[2] % B[1];
00150 if(axis[13](0)==0 && axis[13](1)==0 && axis[13](2)==0)
00151 axis[13] = A[2];
00152 else
00153 axis[13] /= sqrt(axis[13]*axis[13]);
00154 axis[14] = A[2] % B[2];
00155 if(axis[14](0)==0 && axis[14](1)==0 && axis[14](2)==0)
00156 axis[14] = A[2];
00157 else
00158 axis[14] /= sqrt(axis[14]*axis[14]);
00159
00160
00161
00162 real_type min_proj_a[15];
00163 real_type min_proj_b[15];
00164 real_type max_proj_a[15];
00165 real_type max_proj_b[15];
00166 for(unsigned int i=0;i<15;++i)
00167 {
00168 min_proj_a[i] = min_proj_b[i] = math::detail::highest<real_type>();
00169 max_proj_a[i] = max_proj_b[i] = math::detail::lowest<real_type>();
00170 }
00171 for(unsigned int i=0;i<15;++i)
00172 {
00173 for(unsigned int j=0;j<8;++j)
00174 {
00175 real_type proj_a = a[j]*axis[i];
00176 real_type proj_b = b[j]*axis[i];
00177 min_proj_a[i] = min(min_proj_a[i],proj_a);
00178 max_proj_a[i] = max(max_proj_a[i],proj_a);
00179 min_proj_b[i] = min(min_proj_b[i],proj_b);
00180 max_proj_b[i] = max(max_proj_b[i],proj_b);
00181 }
00182
00183 if (min_proj_a[i] > (max_proj_b[i]+envelope) || min_proj_b[i] > (max_proj_a[i]+envelope))
00184 return 0;
00185 }
00186
00187
00188 real_type overlap[15];
00189 real_type minimum_overlap = math::detail::lowest<real_type>();
00190 unsigned int minimum_axis = 15;
00191 bool flip_axis[15];
00192
00193
00194 for(unsigned int i=0;i<15;++i)
00195 {
00196 flip_axis[i] = false;
00197 overlap[i] = math::detail::highest<real_type>();
00198 if(max_proj_a[i] <= min_proj_b[i])
00199 {
00200 overlap[i] = min( overlap[i], min_proj_b[i] - max_proj_a[i] );
00201 if(overlap[i]>minimum_overlap)
00202 {
00203 minimum_overlap = overlap[i];
00204 minimum_axis = i;
00205 flip_axis[i] = false;
00206 }
00207 }
00208 if(max_proj_b[i] <= min_proj_a[i])
00209 {
00210 overlap[i] = min( overlap[i], min_proj_a[i] - max_proj_b[i] );
00211 if(overlap[i]>minimum_overlap)
00212 {
00213 minimum_overlap = overlap[i];
00214 minimum_axis = i;
00215 flip_axis[i] = true;
00216 }
00217 }
00218 if(min_proj_a[i] <= min_proj_b[i] && min_proj_b[i] <= max_proj_a[i])
00219 {
00220 overlap[i] = min( overlap[i], -(max_proj_a[i] - min_proj_b[i]) );
00221 if(overlap[i]>minimum_overlap)
00222 {
00223 minimum_overlap = overlap[i];
00224 minimum_axis = i;
00225 flip_axis[i] = false;
00226 }
00227 }
00228 if(min_proj_b[i] <= min_proj_a[i] && min_proj_a[i] <= max_proj_b[i])
00229 {
00230 overlap[i] = min(overlap[i], -(max_proj_b[i] - min_proj_a[i]) );
00231 if(overlap[i]>minimum_overlap)
00232 {
00233 minimum_overlap = overlap[i];
00234 minimum_axis = i;
00235 flip_axis[i] = true;
00236 }
00237 }
00238 }
00239 if(minimum_overlap>envelope)
00240 return 0;
00241
00242 for(unsigned int i=0;i<15;++i)
00243 {
00244 if(flip_axis[i])
00245 axis[i] = - axis[i];
00246 }
00247
00248
00249
00250 unsigned int corners_inside = 0;
00251 unsigned int corners_B_in_A = 0;
00252 unsigned int corners_A_in_B = 0;
00253 bool AinB[8];
00254 bool BinA[8];
00255
00256 coordsys_type WCStoB(p_b,R_b);
00257 coordsys_type WCStoA(p_a,R_a);
00258
00259 WCStoA = inverse(WCStoA);
00260 WCStoB = inverse(WCStoB);
00261
00262 vector3_type eps_a = ext_a + vector3_type(envelope,envelope,envelope);
00263 vector3_type eps_b = ext_b + vector3_type(envelope,envelope,envelope);
00264 for(unsigned int i=0;i<8;++i)
00265 {
00266 vector3_type a_in_B = a[i];
00267 WCStoB.xform_point(a_in_B);
00268 vector3_type abs_a = fabs(a_in_B);
00269 if(abs_a <= eps_b)
00270 {
00271 ++corners_inside;
00272 ++corners_A_in_B;
00273 AinB[i] = true;
00274 }
00275 else
00276 AinB[i] = false;
00277 vector3_type b_in_A = b[i];
00278 WCStoA.xform_point(b_in_A);
00279 vector3_type abs_b = fabs(b_in_A);
00280 if(abs_b <= eps_a)
00281 {
00282 ++corners_inside;
00283 ++corners_B_in_A;
00284 BinA[i] = true;
00285 }
00286 else
00287 BinA[i] = false;
00288 }
00289
00290 if(minimum_axis >= 6)
00291 {
00292
00293
00294
00295
00296 if(corners_inside)
00297 {
00298 minimum_overlap = math::detail::lowest<real_type>();
00299 minimum_axis = 15;
00300 for(unsigned int i=0;i<6;++i)
00301 {
00302 if(overlap[i]>minimum_overlap)
00303 {
00304 minimum_overlap = overlap[i];
00305 minimum_axis = i;
00306 }
00307 }
00308 }
00309 }
00310
00311
00312
00313 n = axis[minimum_axis];
00314
00315
00316 if(minimum_axis>=6)
00317 {
00318
00319 for(unsigned int i=0;i<3;++i)
00320 if(n*A[i] > 0)
00321 p_a += ext_a(i)*A[i];
00322 else
00323 p_a -= ext_a(i)*A[i];
00324
00325 for(unsigned int i=0;i<3;++i)
00326 if(n*B[i] < 0)
00327 p_b += ext_b(i)*B[i];
00328 else
00329 p_b -= ext_b(i)*B[i];
00330
00331
00332 int columnA = ((minimum_axis)-6)/3;
00333 int columnB = ((minimum_axis)-6)%3;
00334 real_type s,t;
00335
00336
00337
00338 OpenTissue::geometry::compute_closest_points_line_line(p_a, A[columnA], p_b, B[columnB], s, t);
00339
00340
00341 p_a += A[columnA]*s;
00342 p_b += B[columnB]*t;
00343
00344 p[0] = (p_a + p_b)*.5;
00345 distances[0] = overlap[minimum_axis];
00346 return 1;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 vector3_type * R_r,* R_i;
00361 vector3_type ext_r,ext_i;
00362 vector3_type p_r,p_i;
00363 bool * incident_inside;
00364 if (minimum_axis < 3)
00365 {
00366
00367 R_r = A;
00368 R_i = B;
00369 p_r = p_a;
00370 p_i = p_b;
00371 ext_r = ext_a;
00372 ext_i = ext_b;
00373 incident_inside = BinA;
00374 }
00375 else
00376 {
00377
00378 R_r = B;
00379 R_i = A;
00380 p_r = p_b;
00381 p_i = p_a;
00382 ext_r = ext_b;
00383 ext_i = ext_a;
00384 incident_inside = AinB;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 vector3_type n_r_wcs,n_r,abs_n_r;
00441 if (minimum_axis < 3)
00442 {
00443 n_r_wcs = n;
00444 }
00445 else
00446 {
00447 n_r_wcs = -n;
00448 }
00449
00450
00451
00452
00453
00454
00455 n_r(0) = R_i[0] * n_r_wcs;
00456 n_r(1) = R_i[1] * n_r_wcs;
00457 n_r(2) = R_i[2] * n_r_wcs;
00458 abs_n_r(0) = std::fabs (n_r(0));
00459 abs_n_r(1) = std::fabs (n_r(1));
00460 abs_n_r(2) = std::fabs (n_r(2));
00461
00462
00463
00464 int a1,a2,a3;
00465 if (abs_n_r(1) > abs_n_r(0))
00466 {
00467 if (abs_n_r(1) > abs_n_r(2))
00468 {
00469 a1 = 2; a2 = 0; a3 = 1;
00470 }
00471 else
00472 {
00473 a1 = 0; a2 = 1; a3 = 2;
00474 }
00475 }
00476 else
00477 {
00478 if (abs_n_r(0) > abs_n_r(2))
00479 {
00480 a1 = 1; a2 = 2; a3 = 0;
00481 }
00482 else
00483 {
00484 a1 = 0; a2 = 1; a3 = 2;
00485 }
00486 }
00487
00488
00489
00490 int plus_sign[3];
00491 vector3_type center_i_wcs;
00492 if (n_r(a3) < 0)
00493 {
00494 center_i_wcs = p_i + ext_i(a3) * R_i[a3];
00495 plus_sign[a3] = 1;
00496 }
00497 else
00498 {
00499 center_i_wcs = p_i - ext_i(a3) * R_i[a3];
00500 plus_sign[a3] = 0;
00501 }
00502
00503 vector3_type center_ir = center_i_wcs - p_r;
00504
00505 int code1,code2,code3;
00506 if (minimum_axis < 3)
00507 code3 = minimum_axis;
00508 else
00509 code3 = minimum_axis-3;
00510 if (code3==0)
00511 {
00512 code1 = 1;
00513 code2 = 2;
00514 }
00515 else if (code3==1)
00516 {
00517 code1 = 2;
00518 code2 = 0;
00519 }
00520 else
00521 {
00522 code1 = 0;
00523 code2 = 1;
00524 }
00525
00526 real_type quad[8];
00527 bool inside[4];
00528
00529
00530
00531 real_type c1 = R_r[code1] * center_ir;
00532 real_type c2 = R_r[code2] * center_ir;
00533
00534
00535
00536
00537
00538
00539 real_type m11 = R_r[code1] * R_i[a1];
00540 real_type m12 = R_r[code1] * R_i[a2];
00541 real_type m21 = R_r[code2] * R_i[a1];
00542 real_type m22 = R_r[code2] * R_i[a2];
00543 {
00544 real_type k1 = m11 * ext_i(a1);
00545 real_type k2 = m21 * ext_i(a1);
00546 real_type k3 = m12 * ext_i(a2);
00547 real_type k4 = m22 * ext_i(a2);
00548
00549 plus_sign[a1] = 0;
00550 plus_sign[a2] = 0;
00551 unsigned int mask = ( (plus_sign[a1]<<a1) | (plus_sign[a2]<<a2) | (plus_sign[a3]<<a3));
00552 inside[0] = incident_inside[ mask ];
00553
00554 quad[0] = c1 - k1 - k3;
00555 quad[1] = c2 - k2 - k4;
00556
00557 plus_sign[a1] = 0;
00558 plus_sign[a2] = 1;
00559 mask = (plus_sign[a1]<<a1 | plus_sign[a2]<<a2 | plus_sign[a3]<<a3);
00560 inside[1] = incident_inside[ mask ];
00561
00562 quad[2] = c1 - k1 + k3;
00563 quad[3] = c2 - k2 + k4;
00564
00565 plus_sign[a1] = 1;
00566 plus_sign[a2] = 1;
00567 mask = (plus_sign[a1]<<a1 | plus_sign[a2]<<a2 | plus_sign[a3]<<a3);
00568 inside[2] = incident_inside[ mask ];
00569
00570 quad[4] = c1 + k1 + k3;
00571 quad[5] = c2 + k2 + k4;
00572
00573 plus_sign[a1] = 1;
00574 plus_sign[a2] = 0;
00575 mask = (plus_sign[a1]<<a1 | plus_sign[a2]<<a2 | plus_sign[a3]<<a3);
00576 inside[3] = incident_inside[ mask ];
00577
00578 quad[6] = c1 + k1 - k3;
00579 quad[7] = c2 + k2 - k4;
00580 }
00581
00582 real_type rect[2];
00583 rect[0] = ext_r(code1);
00584 rect[1] = ext_r(code2);
00585
00586
00587 real_type crossings[16];
00588 unsigned int edge_crossings = OpenTissue::intersect::rect_quad_edges(rect,quad,inside,crossings);
00589 assert(edge_crossings<=8);
00590
00591 if(!corners_inside && !edge_crossings)
00592 return 0;
00593
00594
00595
00596 real_type det1 = 1./(m11*m22 - m12*m21);
00597 m11 *= det1;
00598 m12 *= det1;
00599 m21 *= det1;
00600 m22 *= det1;
00601 unsigned int cnt = 0;
00602 for (unsigned int j=0; j < edge_crossings; ++j)
00603 {
00604
00605 real_type p0 = crossings[j*2] - c1;
00606 real_type p1 = crossings[j*2+1] - c2;
00607
00608
00609 real_type k1 = m22*p0 - m12*p1;
00610 real_type k2 = -m21*p0 + m11*p1;
00611 vector3_type point = center_ir + k1*R_i[a1] + k2*R_i[a2];
00612
00613 real_type depth = n_r_wcs*point - ext_r(code3);
00614 if(depth<envelope)
00615 {
00616 p[cnt] = point + p_r;
00617 distances[cnt] = depth;
00618 ++cnt;
00619 }
00620 }
00621
00622
00623
00624
00625
00626 if(corners_inside)
00627 {
00628 unsigned int start_corner_A = cnt;
00629 unsigned int end_corner_A = cnt;
00630
00631
00632
00633 real_type w = ext_r(code3) + n_r_wcs*p_r;
00634
00635 if(corners_A_in_B)
00636 {
00637 for (unsigned int i=0; i < 8; ++i)
00638 {
00639 if(AinB[i])
00640 {
00641 vector3_type point = a[i];
00642 real_type depth = n_r_wcs*point - w;
00643 if(depth<envelope)
00644 {
00645 p[cnt] = point;
00646 distances[cnt] = depth;
00647 ++cnt;
00648 }
00649 }
00650 }
00651 end_corner_A = cnt;
00652 }
00653 if(corners_B_in_A)
00654 {
00655 for (unsigned int i=0; i < 8; ++i)
00656 {
00657 if(BinA[i])
00658 {
00659 vector3_type point = b[i];
00660 bool redundant = false;
00661 for(unsigned int j=start_corner_A;j<end_corner_A;++j)
00662 {
00663 if( p[j].is_equal(point,envelope) )
00664 {
00665 redundant = true;
00666 break;
00667 }
00668 }
00669 if(redundant)
00670 continue;
00671 real_type depth = n_r_wcs*point - w;
00672 if(depth<envelope)
00673 {
00674 p[cnt] = point;
00675 distances[cnt] = depth;
00676 ++cnt;
00677 }
00678 }
00679 }
00680 }
00681 }
00682
00683 return cnt;
00684 }
00685
00686 }
00687
00688 }
00689
00690
00691 #endif