LocalMinDistance.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
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 //#include <sofa/component/collision/RayPickInteractor.h>
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>();     // SphereModel are not supported yet
00075     intersectors.ignore<LineModel, SphereModel>();
00076     intersectors.ignore<TriangleModel, SphereModel>();
00077     
00078     
00079     intersectors.add<PointModel, PointModel, LocalMinDistance>(this); // point-point is always activated
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>();            // never the case with LMD
00085     intersectors.ignore<TriangleModel, TriangleModel>();        // never the case with LMD
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* /*contacts*/)
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         // filter for LMD
00150 
00151         if (!testValidity(e1, PQ))
00152             return false;
00153 
00154         Vector3 QP = -PQ;
00155         return testValidity(e2, QP);
00156         // end filter
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 // filter for LMD //
00201         if (!testValidity(e1, PQ))
00202             return 0;
00203 
00204         Vector3 QP = -PQ;
00205         
00206         if (!testValidity(e2, QP))
00207             return 0;
00208 // end filter
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     // We want to find alpha,beta so that:
00250     // AQ = AB*alpha+AC*beta
00251     // PQ.AB = 0 and PQ.AC = 0
00252     // (AQ-AP).AB = 0 and (AQ-AP).AC = 0
00253     // AQ.AB = AP.AB and AQ.AC = AP.AC
00254     //
00255     // (AB*alpha+AC*beta).AB = AP.AB and
00256     // (AB*alpha+AC*beta).AC = AP.AC
00257     //
00258     // AB.AB*alpha + AC.AB*beta = AP.AB and
00259     // AB.AC*alpha + AC.AC*beta = AP.AC
00260     //
00261     // A . [alpha beta] = b
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     //if (det < -0.000000000001 || det > 0.000000000001)
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         //filter for LMD
00288             if (!testValidity(e1, PQ))
00289                 return false;
00290 
00291             Vector3 QP = -PQ;
00292             return testValidity(e2, QP);
00293         // end filter   
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     //if (det < -0.000000000001 || det > 0.000000000001)
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; //PQ
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     // filter for LMD 
00341         if (!testValidity(e1, PQ))
00342             return 0;
00343 
00344         Vector3 QP = -PQ;
00345         
00346         if (!testValidity(e2, QP))
00347             return 0;
00348     //end filter
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     //if (A < -0.000001 || A > 0.000001)
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         // filter for LMD
00409             if (!testValidity(e1, PQ))
00410                 return false;
00411 
00412             Vector3 QP = -PQ;
00413             return testValidity(e2, QP);
00414         // end filter
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     //if (A < -0.000001 || A > 0.000001)
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     // filter for LMD
00450         if (!testValidity(e1, PQ))
00451             return 0;
00452 
00453         Vector3 QP = -PQ;
00454         
00455         if (!testValidity(e2, QP))
00456             return 0;
00457     // end filter
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         // filter for LMD
00497             if (!testValidity(e1, PQ))
00498                 return false;
00499 
00500             Vector3 QP = -PQ;
00501             return testValidity(e2, QP);
00502         // end filter
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     // filter for LMD
00529         if (!testValidity(e1, PQ))
00530             return 0;
00531 
00532         Vector3 QP = -PQ;
00533         
00534         if (!testValidity(e2, QP))
00535             return 0;
00536     // end filter
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     //if (det < -0.000001 || det > 0.000001)
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     //if (det < -0.000001 || det > 0.000001)
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     //if (A < -0.000001 || A > 0.000001)
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     //if (A < -0.000001 || A > 0.000001)
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; // no intersection for edges parallel to the triangle
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         //std::cout<<"Collision between Line - Triangle"<<std::endl;
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; // no intersection for edges parallel to the triangle
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     // filter if there are two triangles around the edge
00909     if (triangleEdgeShell.size() == 2)
00910     {
00911         // compute the normal of the triangle situated on the right
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(); // necessary ?
00918         
00919         // compute the normal of the triangle situated on the left
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(); // necessary ?
00926 
00927         nMean.normalize(); 
00928 
00929         if ((nMean*PQ) < 0) // test 
00930             return false;
00931             
00932         // compute the angle for the cone to filter contacts using the normal of the triangle situated on the right
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         // compute the angle for the cone to filter contacts using the normal of the triangle situated on the left
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 } // namespace collision
00976 
00977 } // namespace component
00978 
00979 } // namespace sofa
00980 

Generated on Sun Nov 23 02:34:11 2008 for Sofa by  doxygen 1.5.7.1