00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/helper/system/config.h>
00026 #include <sofa/component/collision/LocalMinDistance.h>
00027 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00028 #include <sofa/core/ObjectFactory.h>
00029 #include <sofa/component/collision/proximity.h>
00030 #include <sofa/defaulttype/Mat.h>
00031 #include <sofa/defaulttype/Vec.h>
00032 #include <sofa/core/componentmodel/collision/Intersection.inl>
00033
00034 #include <iostream>
00035 #include <algorithm>
00036 #include <sofa/helper/gl/template.h>
00037
00038 #define DYNAMIC_CONE_ANGLE_COMPUTATION
00039
00040 namespace sofa
00041 {
00042
00043 namespace component
00044 {
00045
00046 namespace collision
00047 {
00048
00049 using namespace sofa::defaulttype;
00050 using namespace sofa::core::componentmodel::collision;
00051 using namespace helper;
00052
00053 using core::componentmodel::topology::BaseMeshTopology;
00054 typedef BaseMeshTopology::PointID PointID;
00055
00056 SOFA_DECL_CLASS(LocalMinDistance)
00057
00058 int LocalMinDistanceClass = core::RegisterObject("TODO-LocalMinDistance")
00059 .add< LocalMinDistance >()
00060 ;
00061
00062 LocalMinDistance::LocalMinDistance()
00063 : alarmDistance(initData(&alarmDistance, 1.0, "alarmDistance","Proximity detection distance"))
00064 , contactDistance(initData(&contactDistance, 0.5, "contactDistance","Distance below which a contact is created"))
00065 , angleCone(initData(&angleCone, 0.0, "angleCone","Filtering cone extension angle"))
00066 , coneFactor(initData(&coneFactor, 0.5, "coneFactor", "Factor for filtering cone angle computation"))
00067 {
00068 }
00069
00070 void LocalMinDistance::init()
00071 {
00072 intersectors.add<CubeModel, CubeModel, LocalMinDistance>(this);
00073
00074 intersectors.ignore<SphereModel, PointModel>();
00075 intersectors.ignore<LineModel, SphereModel>();
00076 intersectors.ignore<TriangleModel, SphereModel>();
00077
00078
00079 intersectors.add<PointModel, PointModel, LocalMinDistance>(this);
00080 intersectors.add<LineModel, LineModel, LocalMinDistance>(this);
00081 intersectors.add<LineModel, PointModel, LocalMinDistance>(this);
00082 intersectors.add<TriangleModel, PointModel, LocalMinDistance>(this);
00083
00084 intersectors.ignore<TriangleModel, LineModel>();
00085 intersectors.ignore<TriangleModel, TriangleModel>();
00086
00087 intersectors.ignore<RayModel, PointModel>();
00088 intersectors.ignore<RayModel, LineModel>();
00089 intersectors.add<RayModel, TriangleModel, LocalMinDistance>(this);
00090 }
00091
00092 bool LocalMinDistance::testIntersection(Cube &cube1, Cube &cube2)
00093 {
00094 const Vector3& minVect1 = cube1.minVect();
00095 const Vector3& minVect2 = cube2.minVect();
00096 const Vector3& maxVect1 = cube1.maxVect();
00097 const Vector3& maxVect2 = cube2.maxVect();
00098
00099 const double alarmDist = getAlarmDistance() + cube1.getProximity() + cube2.getProximity();
00100
00101 for (int i=0;i<3;i++)
00102 {
00103 if ( minVect1[i] > maxVect2[i] + alarmDist || minVect2[i]> maxVect1[i] + alarmDist )
00104 return false;
00105 }
00106
00107 return true;
00108 }
00109
00110 int LocalMinDistance::computeIntersection(Cube&, Cube&, OutputVector* )
00111 {
00112 return 0;
00113 }
00114
00115 bool LocalMinDistance::testIntersection(Line& e1, Line& e2)
00116 {
00117 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00118
00119 const Vector3 AB = e1.p2()-e1.p1();
00120 const Vector3 CD = e2.p2()-e2.p1();
00121 const Vector3 AC = e2.p1()-e1.p1();
00122 Matrix2 A;
00123 Vector2 b;
00124
00125 A[0][0] = AB*AB;
00126 A[1][1] = CD*CD;
00127 A[0][1] = A[1][0] = -CD*AB;
00128 b[0] = AB*AC;
00129 b[1] = -CD*AC;
00130
00131 const double det = determinant(A);
00132
00133 double alpha = 0.5;
00134 double beta = 0.5;
00135
00136 if (det < -1.0e-18 || det > 1.0e-18)
00137 {
00138 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00139 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00140 if (alpha < 0.000001 || alpha > 0.999999 ||
00141 beta < 0.000001 || beta > 0.999999 )
00142 return false;
00143 }
00144
00145 Vector3 PQ = AC + CD * beta - AB * alpha;
00146
00147 if (PQ.norm2() < alarmDist*alarmDist)
00148 {
00149
00150
00151 if (!testValidity(e1, PQ))
00152 return false;
00153
00154 Vector3 QP = -PQ;
00155 return testValidity(e2, QP);
00156
00157
00158 }
00159 else
00160 return false;
00161 }
00162
00163 int LocalMinDistance::computeIntersection(Line& e1, Line& e2, OutputVector* contacts)
00164 {
00165 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00166
00167 const Vector3 AB = e1.p2()-e1.p1();
00168 const Vector3 CD = e2.p2()-e2.p1();
00169 const Vector3 AC = e2.p1()-e1.p1();
00170 Matrix2 A;
00171 Vector2 b;
00172
00173 A[0][0] = AB*AB;
00174 A[1][1] = CD*CD;
00175 A[0][1] = A[1][0] = -CD*AB;
00176 b[0] = AB*AC;
00177 b[1] = -CD*AC;
00178 const double det = determinant(A);
00179
00180 double alpha = 0.5;
00181 double beta = 0.5;
00182
00183 if (det < -1.0e-15 || det > 1.0e-15)
00184 {
00185 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00186 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00187 if (alpha < 0.000001 || alpha > 0.999999 ||
00188 beta < 0.000001 || beta > 0.999999 )
00189 return 0;
00190 }
00191
00192 Vector3 P,Q,PQ;
00193 P = e1.p1() + AB * alpha;
00194 Q = e2.p1() + CD * beta;
00195 PQ = Q-P;
00196
00197 if (PQ.norm2() >= alarmDist*alarmDist)
00198 return 0;
00199
00200
00201 if (!testValidity(e1, PQ))
00202 return 0;
00203
00204 Vector3 QP = -PQ;
00205
00206 if (!testValidity(e2, QP))
00207 return 0;
00208
00209
00210 #ifdef DETECTIONOUTPUT_FREEMOTION
00211
00212 Vector3 Pfree,Qfree,ABfree,CDfree;
00213 ABfree = e1.p2Free()-e1.p1Free();
00214 CDfree = e2.p2Free()-e2.p1Free();
00215 Pfree = e1.p1Free() + ABfree * alpha;
00216 Qfree = e2.p1Free() + CDfree * beta;
00217
00218 #endif
00219
00220 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00221
00222 contacts->resize(contacts->size()+1);
00223 DetectionOutput *detection = &*(contacts->end()-1);
00224 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00225 detection->id = (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex();
00226 detection->point[0]=P;
00227 detection->point[1]=Q;
00228 #ifdef DETECTIONOUTPUT_FREEMOTION
00229 detection->freePoint[0]=Pfree;
00230 detection->freePoint[1]=Qfree;
00231 #endif
00232 detection->normal=PQ;
00233 detection->value = detection->normal.norm();
00234 detection->normal /= detection->value;
00235 detection->value -= contactDist;
00236 return 1;
00237 }
00238
00239 bool LocalMinDistance::testIntersection(Triangle& e2, Point& e1)
00240 {
00241 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00242
00243 const Vector3 AB = e2.p2()-e2.p1();
00244 const Vector3 AC = e2.p3()-e2.p1();
00245 const Vector3 AP = e1.p() -e2.p1();
00246 Matrix2 A;
00247 Vector2 b;
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 A[0][0] = AB*AB;
00263 A[1][1] = AC*AC;
00264 A[0][1] = A[1][0] = AB*AC;
00265 b[0] = AP*AB;
00266 b[1] = AP*AC;
00267 const double det = determinant(A);
00268
00269 double alpha = 0.5;
00270 double beta = 0.5;
00271
00272
00273 {
00274 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00275 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00276 if (alpha < 0.000001 ||
00277 beta < 0.000001 ||
00278 alpha + beta > 0.999999)
00279 return false;
00280 }
00281
00282 const Vector3 PQ = AB * alpha + AC * beta - AP;
00283
00284 if (PQ.norm2() < alarmDist*alarmDist)
00285 {
00286
00287
00288 if (!testValidity(e1, PQ))
00289 return false;
00290
00291 Vector3 QP = -PQ;
00292 return testValidity(e2, QP);
00293
00294
00295 }
00296 else
00297 return false;
00298 }
00299
00300 int LocalMinDistance::computeIntersection(Triangle& e2, Point& e1, OutputVector* contacts)
00301 {
00302 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00303
00304 const Vector3 AB = e2.p2()-e2.p1();
00305 const Vector3 AC = e2.p3()-e2.p1();
00306 const Vector3 AP = e1.p() -e2.p1();
00307 Matrix2 A;
00308 Vector2 b;
00309
00310 A[0][0] = AB*AB;
00311 A[1][1] = AC*AC;
00312 A[0][1] = A[1][0] = AB*AC;
00313 b[0] = AP*AB;
00314 b[1] = AP*AC;
00315
00316 const double det = determinant(A);
00317
00318 double alpha = 0.5;
00319 double beta = 0.5;
00320
00321
00322 {
00323 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00324 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00325 if (alpha < 0.000001 ||
00326 beta < 0.000001 ||
00327 alpha + beta > 0.999999)
00328 return 0;
00329 }
00330
00331 Vector3 P,Q;
00332 P = e1.p();
00333 Q = e2.p1() + AB * alpha + AC * beta;
00334 Vector3 PQ = Q-P;
00335
00336 if (PQ.norm2() >= alarmDist*alarmDist)
00337 return 0;
00338
00339
00340
00341 if (!testValidity(e1, PQ))
00342 return 0;
00343
00344 Vector3 QP = -PQ;
00345
00346 if (!testValidity(e2, QP))
00347 return 0;
00348
00349
00350
00351 #ifdef DETECTIONOUTPUT_FREEMOTION
00352
00353 Vector3 Pfree,Qfree,ABfree,ACfree;
00354 ABfree = e2.p2Free()-e2.p1Free();
00355 ACfree = e2.p3Free()-e2.p1Free();
00356 Pfree = e1.pFree();
00357 Qfree = e2.p1Free() + ABfree * alpha + ACfree * beta;
00358
00359 #endif
00360
00361 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00362
00363 contacts->resize(contacts->size()+1);
00364 DetectionOutput *detection = &*(contacts->end()-1);
00365 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e2, e1);
00366 detection->id = e1.getIndex();
00367 detection->point[0]=Q;
00368 detection->point[1]=P;
00369 #ifdef DETECTIONOUTPUT_FREEMOTION
00370 detection->freePoint[0]=Qfree;
00371 detection->freePoint[1]=Pfree;
00372 #endif
00373 detection->normal = QP;
00374 detection->value = detection->normal.norm();
00375 detection->normal /= detection->value;
00376 detection->value -= contactDist;
00377 return 1;
00378 }
00379
00380 bool LocalMinDistance::testIntersection(Line& e2, Point& e1)
00381 {
00382
00383 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00384 const Vector3 AB = e2.p2()-e2.p1();
00385 const Vector3 AP = e1.p()-e2.p1();
00386
00387 double A;
00388 double b;
00389 A = AB*AB;
00390 b = AP*AB;
00391
00392 double alpha = 0.5;
00393
00394
00395 {
00396 alpha = b/A;
00397 if (alpha < 0.000001 || alpha > 0.999999)
00398 return false;
00399 }
00400
00401 Vector3 P,Q,PQ;
00402 P = e1.p();
00403 Q = e2.p1() + AB * alpha;
00404 PQ = Q-P;
00405
00406 if (PQ.norm2() < alarmDist*alarmDist)
00407 {
00408
00409 if (!testValidity(e1, PQ))
00410 return false;
00411
00412 Vector3 QP = -PQ;
00413 return testValidity(e2, QP);
00414
00415 }
00416 else
00417 return false;
00418 }
00419
00420 int LocalMinDistance::computeIntersection(Line& e2, Point& e1, OutputVector* contacts)
00421 {
00422 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00423 const Vector3 AB = e2.p2()-e2.p1();
00424 const Vector3 AP = e1.p()-e2.p1();
00425
00426 double A;
00427 double b;
00428 A = AB*AB;
00429 b = AP*AB;
00430
00431 double alpha = 0.5;
00432
00433
00434 {
00435 alpha = b/A;
00436 if (alpha < 0.000001 || alpha > 0.999999)
00437 return 0;
00438 }
00439
00440 Vector3 P,Q;
00441 P = e1.p();
00442 Q = e2.p1() + AB * alpha;
00443 Vector3 PQ = Q-P;
00444
00445 if (PQ.norm2() >= alarmDist*alarmDist)
00446 return 0;
00447
00448
00449
00450 if (!testValidity(e1, PQ))
00451 return 0;
00452
00453 Vector3 QP = -PQ;
00454
00455 if (!testValidity(e2, QP))
00456 return 0;
00457
00458
00459 #ifdef DETECTIONOUTPUT_FREEMOTION
00460
00461
00462 Vector3 ABfree = e2.p2Free()-e2.p1Free();
00463 Vector3 Pfree = e1.pFree();
00464 Vector3 Qfree = e2.p1Free() + ABfree * alpha;
00465
00466 #endif
00467
00468 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00469
00470 contacts->resize(contacts->size()+1);
00471 DetectionOutput *detection = &*(contacts->end()-1);
00472
00473 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e2, e1);
00474 detection->id = e1.getIndex();
00475 detection->point[0]=Q;
00476 detection->point[1]=P;
00477 #ifdef DETECTIONOUTPUT_FREEMOTION
00478 detection->freePoint[0]=Qfree;
00479 detection->freePoint[1]=Pfree;
00480 #endif
00481 detection->normal=QP;
00482 detection->value = detection->normal.norm();
00483 detection->normal /= detection->value;
00484 detection->value -= contactDist;
00485 return 1;
00486 }
00487
00488 bool LocalMinDistance::testIntersection(Point& e1, Point& e2)
00489 {
00490 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00491
00492 Vector3 PQ = e2.p()-e1.p();
00493
00494 if (PQ.norm2() < alarmDist*alarmDist)
00495 {
00496
00497 if (!testValidity(e1, PQ))
00498 return false;
00499
00500 Vector3 QP = -PQ;
00501 return testValidity(e2, QP);
00502
00503 }
00504 else
00505 return false;
00506 }
00507
00508 int LocalMinDistance::computeIntersection(Point& e1, Point& e2, OutputVector* contacts)
00509 {
00510
00511 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00512
00513 Vector3 P,Q,PQ;
00514 P = e1.p();
00515 Q = e2.p();
00516 PQ = Q-P;
00517
00518 #ifdef DETECTIONOUTPUT_FREEMOTION
00519 Vector3 Pfree,Qfree;
00520 Pfree = e1.pFree();
00521 Qfree = e2.pFree();
00522 #endif
00523
00524
00525 if (PQ.norm2() >= alarmDist*alarmDist)
00526 return 0;
00527
00528
00529 if (!testValidity(e1, PQ))
00530 return 0;
00531
00532 Vector3 QP = -PQ;
00533
00534 if (!testValidity(e2, QP))
00535 return 0;
00536
00537
00538 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00539
00540 contacts->resize(contacts->size()+1);
00541 DetectionOutput *detection = &*(contacts->end()-1);
00542 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00543 detection->id = (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex();
00544 detection->point[0]=P;
00545 detection->point[1]=Q;
00546 #ifdef DETECTIONOUTPUT_FREEMOTION
00547 detection->freePoint[0]=Pfree;
00548 detection->freePoint[1]=Qfree;
00549 #endif
00550 detection->normal=PQ;
00551 detection->value = detection->normal.norm();
00552 detection->normal /= detection->value;
00553 detection->value -= contactDist;
00554 return 1;
00555 }
00556
00557
00558
00559 bool LocalMinDistance::testIntersection(Triangle& e2, Sphere& e1)
00560 {
00561 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00562
00563 const Vector3 x13 = e2.p1()-e2.p2();
00564 const Vector3 x23 = e2.p1()-e2.p3();
00565 const Vector3 x03 = e2.p1()-e1.center();
00566 Matrix2 A;
00567 Vector2 b;
00568 A[0][0] = x13*x13;
00569 A[1][1] = x23*x23;
00570 A[0][1] = A[1][0] = x13*x23;
00571 b[0] = x13*x03;
00572 b[1] = x23*x03;
00573 const double det = determinant(A);
00574
00575 double alpha = 0.5;
00576 double beta = 0.5;
00577
00578
00579 {
00580 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00581 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00582 if (alpha < 0.000001 ||
00583 beta < 0.000001 ||
00584 alpha + beta > 0.999999)
00585 return false;
00586 }
00587
00588 Vector3 P,Q,PQ;
00589 P = e1.center();
00590 Q = e2.p1() - x13 * alpha - x23 * beta;
00591 PQ = Q-P;
00592
00593 if (PQ.norm2() < alarmDist*alarmDist)
00594 {
00595 return true;
00596 }
00597 else
00598 return false;
00599 }
00600
00601 int LocalMinDistance::computeIntersection(Triangle& e2, Sphere& e1, OutputVector* contacts)
00602 {
00603 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00604
00605 const Vector3 x13 = e2.p1()-e2.p2();
00606 const Vector3 x23 = e2.p1()-e2.p3();
00607 const Vector3 x03 = e2.p1()-e1.center();
00608 Matrix2 A;
00609 Vector2 b;
00610 A[0][0] = x13*x13;
00611 A[1][1] = x23*x23;
00612 A[0][1] = A[1][0] = x13*x23;
00613 b[0] = x13*x03;
00614 b[1] = x23*x03;
00615 const double det = determinant(A);
00616
00617 double alpha = 0.5;
00618 double beta = 0.5;
00619
00620
00621 {
00622 alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00623 beta = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00624 if (alpha < 0.000001 ||
00625 beta < 0.000001 ||
00626 alpha + beta > 0.999999)
00627 return 0;
00628 }
00629
00630 Vector3 P = e1.center();
00631 Vector3 Q = e2.p1() - x13 * alpha - x23 * beta;
00632 Vector3 QP = P-Q;
00633 Vector3 PQ = Q-P;
00634
00635 if (QP.norm2() >= alarmDist*alarmDist)
00636 return 0;
00637
00638 const double contactDist = getContactDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00639
00640 contacts->resize(contacts->size()+1);
00641 DetectionOutput *detection = &*(contacts->end()-1);
00642 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e2, e1);
00643 detection->id = e1.getIndex();
00644 detection->point[0]=Q;
00645 detection->point[1]=P;
00646 detection->normal=QP;
00647 detection->value = detection->normal.norm();
00648 detection->normal /= detection->value;
00649 detection->value -= contactDist;
00650 return 1;
00651 }
00652
00653 bool LocalMinDistance::testIntersection(Line& e2, Sphere& e1)
00654 {
00655 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00656
00657 const Vector3 x32 = e2.p1()-e2.p2();
00658 const Vector3 x31 = e1.center()-e2.p2();
00659 double A;
00660 double b;
00661 A = x32*x32;
00662 b = x32*x31;
00663
00664 double alpha = 0.5;
00665
00666
00667 {
00668 alpha = b/A;
00669 if (alpha < 0.000001 || alpha > 0.999999)
00670 return false;
00671 }
00672
00673 Vector3 P,Q,PQ;
00674 P = e1.center();
00675 Q = e2.p1() - x32 * alpha;
00676 PQ = Q-P;
00677
00678 if (PQ.norm2() < alarmDist*alarmDist)
00679 {
00680 return true;
00681 }
00682 else
00683 return false;
00684 }
00685
00686 int LocalMinDistance::computeIntersection(Line& e2, Sphere& e1, OutputVector* contacts)
00687 {
00688 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00689
00690 const Vector3 x32 = e2.p1()-e2.p2();
00691 const Vector3 x31 = e1.center()-e2.p2();
00692 double A;
00693 double b;
00694 A = x32*x32;
00695 b = x32*x31;
00696
00697 double alpha = 0.5;
00698
00699
00700 {
00701 alpha = b/A;
00702 if (alpha < 0.000001 || alpha > 0.999999)
00703 return 0;
00704 }
00705
00706 Vector3 P = e1.center();
00707 Vector3 Q = e2.p1() - x32 * alpha;
00708 Vector3 QP = P-Q;
00709 Vector3 PQ = Q-P;
00710
00711 if (QP.norm2() >= alarmDist*alarmDist)
00712 return 0;
00713
00714 const double contactDist = getContactDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00715
00716 contacts->resize(contacts->size()+1);
00717 DetectionOutput *detection = &*(contacts->end()-1);
00718 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e2, e1);
00719 detection->id = e1.getIndex();
00720 detection->point[0]=Q;
00721 detection->point[1]=P;
00722 detection->normal=QP;
00723 detection->value = detection->normal.norm();
00724 detection->normal /= detection->value;
00725 detection->value -= contactDist;
00726 return 1;
00727 }
00728
00729 bool LocalMinDistance::testIntersection(Sphere& e1, Point& e2)
00730 {
00731 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00732
00733 Vector3 P,Q,PQ;
00734 P = e1.center();
00735 Q = e2.p();
00736 PQ = Q-P;
00737
00738 if (PQ.norm2() < alarmDist*alarmDist)
00739 {
00740 return true;
00741 }
00742 else
00743 return false;
00744 }
00745
00746 int LocalMinDistance::computeIntersection(Sphere& e1, Point& e2, OutputVector* contacts)
00747 {
00748 const double alarmDist = getAlarmDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00749
00750 Vector3 P,Q,PQ;
00751 P = e1.center();
00752 Q = e2.p();
00753 PQ = Q-P;
00754 if (PQ.norm2() >= alarmDist*alarmDist)
00755 return 0;
00756
00757 const double contactDist = getContactDistance() + e1.r() + e1.getProximity() + e2.getProximity();
00758
00759 contacts->resize(contacts->size()+1);
00760 DetectionOutput *detection = &*(contacts->end()-1);
00761 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00762 detection->id = (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex();
00763 detection->point[0]=P;
00764 detection->point[1]=Q;
00765 detection->normal=PQ;
00766 detection->value = detection->normal.norm();
00767 detection->normal /= detection->value;
00768 detection->value -= contactDist;
00769 return 1;
00770 }
00771
00772 bool LocalMinDistance::testIntersection(Ray &t1,Triangle &t2)
00773 {
00774 Vector3 P,Q,PQ;
00775 static DistanceSegTri proximitySolver;
00776
00777 const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00778
00779 if (fabs(t2.n() * t1.direction()) < 0.000001)
00780 return false;
00781
00782 Vector3 A = t1.origin();
00783 Vector3 B = A + t1.direction() * t1.l();
00784
00785 proximitySolver.NewComputation( &t2, A, B,P,Q);
00786 PQ = Q-P;
00787
00788 if (PQ.norm2() < alarmDist*alarmDist)
00789 {
00790
00791 return true;
00792 }
00793 else
00794 return false;
00795 }
00796
00797 int LocalMinDistance::computeIntersection(Ray &t1, Triangle &t2, OutputVector* contacts)
00798 {
00799 const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00800
00801
00802 if (fabs(t2.n() * t1.direction()) < 0.000001)
00803 return false;
00804
00805 Vector3 A = t1.origin();
00806 Vector3 B = A + t1.direction() * t1.l();
00807
00808 Vector3 P,Q,PQ;
00809 static DistanceSegTri proximitySolver;
00810
00811 proximitySolver.NewComputation( &t2, A,B,P,Q);
00812 PQ = Q-P;
00813
00814 if (PQ.norm2() >= alarmDist*alarmDist)
00815 return 0;
00816
00817 const double contactDist = alarmDist;
00818 contacts->resize(contacts->size()+1);
00819 DetectionOutput *detection = &*(contacts->end()-1);
00820
00821 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(t1, t2);
00822 detection->id = t1.getIndex();
00823 detection->point[1]=P;
00824 detection->point[0]=Q;
00825 #ifdef DETECTIONOUTPUT_FREEMOTION
00826 detection->freePoint[1] = P;
00827 detection->freePoint[0] = Q;
00828 #endif
00829 detection->normal=-t2.n();
00830 detection->value = PQ.norm();
00831 detection->value -= contactDist;
00832 return 1;
00833 }
00834
00835
00836 bool LocalMinDistance::testValidity(Point &p, const Vector3 &PQ)
00837 {
00838 Vector3 pt = p.p();
00839
00840 BaseMeshTopology* topology = p.getCollisionModel()->getMeshTopology();
00841 helper::vector<Vector3>& x = *(p.getCollisionModel()->getMechanicalState()->getX());
00842
00843 const helper::vector <unsigned int>& triangleVertexShell = topology->getTriangleVertexShell(p.getIndex());
00844 const helper::vector <unsigned int>& edgeVertexShell = topology->getEdgeVertexShell(p.getIndex());
00845
00846
00847 Vector3 nMean;
00848
00849 for (unsigned int i=0; i<triangleVertexShell.size(); i++)
00850 {
00851 unsigned int t = triangleVertexShell[i];
00852 const fixed_array<unsigned int,3>& ptr = topology->getTriangle(t);
00853 Vector3 nCur = (x[ptr[1]]-x[ptr[0]]).cross(x[ptr[2]]-x[ptr[0]]);
00854 nCur.normalize();
00855 nMean += nCur;
00856 }
00857
00858 if (triangleVertexShell.size()==0)
00859 {
00860 for (unsigned int i=0; i<edgeVertexShell.size(); i++)
00861 {
00862 unsigned int e = edgeVertexShell[i];
00863 const fixed_array<unsigned int,2>& ped = topology->getEdge(e);
00864 Vector3 l = (pt - x[ped[0]]) + (pt - x[ped[1]]);
00865 l.normalize();
00866 nMean += l;
00867 }
00868 }
00869
00870 if (nMean.norm()> 0.0000000001)
00871 nMean.normalize();
00872
00873
00874 for (unsigned int i=0; i<edgeVertexShell.size(); i++)
00875 {
00876 unsigned int e = edgeVertexShell[i];
00877 const fixed_array<unsigned int,2>& ped = topology->getEdge(e);
00878 Vector3 l = (pt - x[ped[0]]) + (pt - x[ped[1]]);
00879 l.normalize();
00880 double computedAngleCone = dot(nMean , l) * coneFactor.getValue();
00881 if (computedAngleCone<0)
00882 computedAngleCone=0.0;
00883 computedAngleCone+=angleCone.getValue();
00884 if (dot(l , PQ) < -computedAngleCone*PQ.norm())
00885 return false;
00886 }
00887 return true;
00888
00889 }
00890
00891 bool LocalMinDistance::testValidity(Line &l, const Vector3 &PQ)
00892 {
00893 Vector3 nMean;
00894 Vector3 n1, n2;
00895 Vector3 t1, t2;
00896
00897 const Vector3 &pt1 = l.p1();
00898 const Vector3 &pt2 = l.p2();
00899
00900 Vector3 AB = pt2 - pt1;
00901 AB.normalize();
00902
00903 BaseMeshTopology* topology = l.getCollisionModel()->getMeshTopology();
00904 helper::vector<Vector3>& x = *(l.getCollisionModel()->getMechanicalState()->getX());
00905
00906 const sofa::helper::vector<unsigned int>& triangleEdgeShell = topology->getTriangleEdgeShell(l.getIndex());
00907
00908
00909 if (triangleEdgeShell.size() == 2)
00910 {
00911
00912 const BaseMeshTopology::Triangle& triangleRight = topology->getTriangle(triangleEdgeShell[0]);
00913 n1 = cross(x[triangleRight[1]]-x[triangleRight[0]], x[triangleRight[2]]-x[triangleRight[0]]);
00914 n1.normalize();
00915 nMean = n1;
00916 t1 = -cross(n1, AB);
00917 t1.normalize();
00918
00919
00920 const fixed_array<PointID,3>& triangleLeft = topology->getTriangle(triangleEdgeShell[1]);
00921 n2 = cross(x[triangleLeft[1]]-x[triangleLeft[0]], x[triangleLeft[2]]-x[triangleLeft[0]]);
00922 n2.normalize();
00923 nMean += n2;
00924 t2 = -cross(AB, n2);
00925 t2.normalize();
00926
00927 nMean.normalize();
00928
00929 if ((nMean*PQ) < 0)
00930 return false;
00931
00932
00933 double computedAngleCone = (nMean * t1) * coneFactor.getValue();
00934 if (computedAngleCone<0)
00935 computedAngleCone=0.0;
00936 computedAngleCone+=angleCone.getValue();
00937
00938 if (t1*PQ < -computedAngleCone*PQ.norm())
00939 return false;
00940
00941
00942 computedAngleCone = (nMean * t2) * coneFactor.getValue();
00943 if (computedAngleCone<0)
00944 computedAngleCone=0.0;
00945 computedAngleCone+=angleCone.getValue();
00946
00947 if (t2*PQ < -computedAngleCone*PQ.norm())
00948 return false;
00949
00950 }
00951 return true;
00952
00953
00954 }
00955
00956 bool LocalMinDistance::testValidity(Triangle &t, const Vector3 &PQ)
00957 {
00958 const Vector3& pt1 = t.p1();
00959 const Vector3& pt2 = t.p2();
00960 const Vector3& pt3 = t.p3();
00961
00962 Vector3 n = cross(pt2-pt1,pt3-pt1);
00963
00964 return ( (n*PQ) >= 0.0);
00965 }
00966
00967
00968 void LocalMinDistance::draw()
00969 {
00970 if (!getContext()->getShowCollisionModels())
00971 return;
00972 }
00973
00974
00975 }
00976
00977 }
00978
00979 }
00980