NewProximityIntersection.inl

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 #ifndef SOFA_COMPONENT_COLLISION_NEWPROXIMITYINTERSECTION_INL
00026 #define SOFA_COMPONENT_COLLISION_NEWPROXIMITYINTERSECTION_INL
00027 
00028 #include <sofa/helper/system/config.h>
00029 #include <sofa/component/collision/NewProximityIntersection.h>
00030 #include <sofa/component/collision/proximity.h>
00031 #include <sofa/defaulttype/Mat.h>
00032 #include <sofa/defaulttype/Vec.h>
00033 #include <sofa/core/componentmodel/collision/Intersection.inl>
00034 #include <iostream>
00035 #include <algorithm>
00036 
00037 
00038 namespace sofa
00039 {
00040 
00041 namespace component
00042 {
00043 
00044 namespace collision
00045 {
00046 
00047 using namespace sofa::defaulttype;
00048 using namespace sofa::core::componentmodel::collision;
00049 using namespace helper;
00050 
00051 inline int NewProximityIntersection::doIntersectionLineLine(double dist2, const Vector3& p1, const Vector3& p2, const Vector3& q1, const Vector3& q2, OutputVector* contacts, int id)
00052 {
00053     const Vector3 AB = p2-p1;
00054     const Vector3 CD = q2-q1;
00055     const Vector3 AC = q1-p1;
00056     Matrix2 A;
00057     Vector2 b;
00058     A[0][0] = AB*AB;
00059     A[1][1] = CD*CD;
00060     A[0][1] = A[1][0] = -CD*AB;
00061     b[0] = AB*AC;
00062     b[1] = -CD*AC;
00063     const double det = determinant(A);
00064 
00065     double alpha = 0.5;
00066     double beta = 0.5;
00067 
00068     if (det < -0.000000000001 || det > 0.000000000001)
00069     {
00070             alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00071             beta  = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00072             //if (alpha < 0.000001 || alpha > 0.999999 ||
00073             //    beta  < 0.000001 || beta  > 0.999999 )
00074             //        return 0;
00075             if (alpha < 0.0) alpha = 0.0;
00076             else if (alpha > 1.0) alpha = 1.0;
00077             if (beta < 0.0) beta = 0.0;
00078             else if (beta > 1.0) beta = 1.0;
00079     }
00080 
00081     Vector3 p,q,pq;
00082     p = p1 + AB * alpha;
00083     q = q1 + CD * beta;
00084     pq = q-p;
00085     if (pq.norm2() >= dist2)
00086             return 0;
00087 
00088     //const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00089     contacts->resize(contacts->size()+1);
00090     DetectionOutput *detection = &*(contacts->end()-1);
00091     //detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00092     detection->id = id;
00093     detection->point[0]=p;
00094     detection->point[1]=q;
00095     detection->normal=pq;
00096     detection->value = detection->normal.norm();
00097     detection->normal /= detection->value;
00098     //detection->value -= contactDist;
00099     return 1;
00100 }
00101 
00102 inline int NewProximityIntersection::doIntersectionLinePoint(double dist2, const Vector3& p1, const Vector3& p2, const Vector3& q, OutputVector* contacts, int id, bool swapElems)
00103 {
00104     const Vector3 AB = p2-p1;
00105     const Vector3 AQ = q -p1;
00106     double A;
00107     double b;
00108     A = AB*AB;
00109     b = AQ*AB;
00110 
00111     double alpha = 0.5;
00112 
00113     //if (A < -0.000001 || A > 0.000001)
00114     {
00115             alpha = b/A;
00116             //if (alpha < 0.000001 || alpha > 0.999999)
00117             //        return 0;
00118             if (alpha < 0.0) alpha = 0.0;
00119             else if (alpha > 1.0) alpha = 1.0;
00120     }
00121 
00122     Vector3 p,pq;
00123     p = p1 + AB * alpha;
00124     pq = q-p;
00125     if (pq.norm2() >= dist2)
00126             return 0;
00127 
00128     //const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00129     contacts->resize(contacts->size()+1);
00130     DetectionOutput *detection = &*(contacts->end()-1);
00131     
00132     //detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e2, e1);
00133     detection->id = id;
00134     if (swapElems)
00135     {
00136         detection->point[0]=q;
00137         detection->point[1]=p;
00138         detection->normal = -pq;
00139     }
00140     else
00141     {
00142         detection->point[0]=p;
00143         detection->point[1]=q;
00144         detection->normal = pq;
00145     }
00146     detection->value = detection->normal.norm();
00147     detection->normal /= detection->value;
00148     //detection->value -= contactDist;
00149     return 1;
00150 }
00151 
00152 inline int NewProximityIntersection::doIntersectionPointPoint(double dist2, const Vector3& p, const Vector3& q, OutputVector* contacts, int id)
00153 {
00154     Vector3 pq;
00155     pq = q-p;
00156     if (pq.norm2() >= dist2)
00157             return 0;
00158 
00159     //const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00160     contacts->resize(contacts->size()+1);
00161     DetectionOutput *detection = &*(contacts->end()-1);
00162     //detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00163     detection->id = id;
00164     detection->point[0]=p;
00165     detection->point[1]=q;
00166     detection->normal=pq;
00167     detection->value = detection->normal.norm();
00168     detection->normal /= detection->value;
00169     //detection->value -= contactDist;
00170     return 1;
00171 }
00172 
00173 inline int NewProximityIntersection::doIntersectionTrianglePoint(double dist2, int flags, const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& /*n*/, const Vector3& q, OutputVector* contacts, int id, bool swapElems)
00174 {
00175     const Vector3 AB = p2-p1;
00176     const Vector3 AC = p3-p1;
00177     const Vector3 AQ = q -p1;
00178     Matrix2 A;
00179     Vector2 b;
00180     A[0][0] = AB*AB;
00181     A[1][1] = AC*AC;
00182     A[0][1] = A[1][0] = AB*AC;
00183     b[0] = AQ*AB;
00184     b[1] = AQ*AC;
00185     const double det = determinant(A);
00186 
00187     double alpha = 0.5;
00188     double beta = 0.5;
00189 
00190     //if (det < -0.000000000001 || det > 0.000000000001)
00191     {
00192         alpha = (b[0]*A[1][1] - b[1]*A[0][1])/det;
00193         beta  = (b[1]*A[0][0] - b[0]*A[1][0])/det;
00194         //if (alpha < 0.000001 ||
00195         //    beta  < 0.000001 ||
00196         //    alpha + beta  > 0.999999)
00197         //        return 0;
00198         if (alpha < 0.000001 || beta < 0.000001 || alpha + beta > 0.999999)
00199         { // nearest point is on an edge or corner
00200             // barycentric coordinate on AB
00201             double pAB = b[0] / A[0][0]; // AQ*AB / AB*AB
00202             // barycentric coordinate on AC
00203             double pAC = b[1] / A[1][1]; // AQ*AB / AB*AB
00204             if (pAB < 0.000001 && pAC < 0.0000001)
00205             {   // closest point is A
00206                 if (!(flags&TriangleModel::FLAG_P1)) return 0; // this corner is not considered
00207                 alpha = 0.0;
00208                 beta = 0.0;
00209             }
00210             else if (pAB < 0.999999 && beta < 0.000001)
00211             {   // closest point is on AB
00212                 if (!(flags&TriangleModel::FLAG_E12)) return 0; // this edge is not considered
00213                 alpha = pAB;
00214                 beta = 0.0;
00215             }
00216             else if (pAC < 0.999999 && alpha < 0.000001)
00217             {   // closest point is on AC
00218                 if (!(flags&TriangleModel::FLAG_E12)) return 0; // this edge is not considered
00219                 alpha = 0.0;
00220                 beta = pAC;
00221             }
00222             else
00223             {
00224                 // barycentric coordinate on BC
00225                 // BQ*BC / BC*BC = (AQ-AB)*(AC-AB) / (AC-AB)*(AC-AB) = (AQ*AC-AQ*AB + AB*AB-AB*AC) / (AB*AB+AC*AC-2AB*AC)
00226                 double pBC = (b[1] - b[0] + A[0][0] - A[1][1]) / (A[0][0] + A[1][1] - 2*A[0][1]); // BQ*BC / BC*BC
00227                 if (pBC < 0.000001)
00228                 {   // closest point is B
00229                     if (!(flags&TriangleModel::FLAG_P2)) return 0; // this edge is not considered
00230                     alpha = 1.0;
00231                     beta = 0.0;
00232                 }
00233                 else if (pBC > 0.999999)
00234                 {   // closest point is C
00235                     if (!(flags&TriangleModel::FLAG_P3)) return 0; // this edge is not considered
00236                     alpha = 0.0;
00237                     beta = 1.0;
00238                 }
00239                 else
00240                 {   // closest point is on BC
00241                     if (!(flags&TriangleModel::FLAG_E31)) return 0; // this edge is not considered
00242                     alpha = 1.0-pBC;
00243                     beta = pBC;
00244                 }
00245             }
00246         }
00247     }
00248 
00249     Vector3 p, pq;
00250     p = p1 + AB * alpha + AC * beta;
00251     pq = q-p;
00252     if (pq.norm2() >= dist2)
00253             return 0;
00254 
00255     //const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00256     contacts->resize(contacts->size()+1);
00257     DetectionOutput *detection = &*(contacts->end()-1);
00258     //detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00259     detection->id = id;
00260     if (swapElems)
00261     {
00262         detection->point[0]=q;
00263         detection->point[1]=p;
00264         detection->normal = -pq;
00265     }
00266     else
00267     {
00268         detection->point[0]=p;
00269         detection->point[1]=q;
00270         detection->normal = pq;
00271     }
00272     detection->value = detection->normal.norm();
00273     detection->normal /= detection->value;
00274 
00275     //printf("\n normale : x = %f , y = %f, z = %f",detection->normal.x(),detection->normal.y(),detection->normal.z());
00276     //if (e2.getCollisionModel()->isStatic() && detection->normal * e2.n() < -0.95)
00277     //{ // The elements are interpenetrating
00278     //  detection->normal = -detection->normal;
00279     //  detection->value = -detection->value;
00280     //}
00281     //detection->value -= contactDist;
00282     return 1;
00283 }
00284 
00285 template<class Sphere>
00286 bool NewProximityIntersection::testIntersection(Sphere& e1, Point& e2)
00287 {
00288     OutputVector contacts;
00289     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e1.r();
00290     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.center(), e2.p(), &contacts, -1);
00291     return n>0;
00292 }
00293 
00294 template<class Sphere>
00295 int NewProximityIntersection::computeIntersection(Sphere& e1, Point& e2, OutputVector* contacts)
00296 {
00297     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e1.r();
00298     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.center(), e2.p(), contacts, (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex());
00299     if (n>0)
00300     {
00301         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity() + e1.r();
00302         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00303         {
00304             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00305             detection->value -= contactDist;
00306         }
00307     }
00308     return n;
00309 }
00310 
00311 template<class Sphere>
00312 bool NewProximityIntersection::testIntersection(Sphere& e1, Sphere& e2)
00313 {
00314     OutputVector contacts;
00315     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e1.r() + e2.r();
00316     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.center(), e2.center(), &contacts, -1);
00317     return n>0;
00318 }
00319 
00320 template<class Sphere>
00321 int NewProximityIntersection::computeIntersection(Sphere& e1, Sphere& e2, OutputVector* contacts)
00322 {
00323     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e1.r() + e2.r();
00324     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.center(), e2.center(), contacts, (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex());
00325     if (n>0)
00326     {
00327         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity() + e1.r() + e2.r();
00328         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00329         {
00330             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00331             detection->value -= contactDist;
00332         }
00333     }
00334     return n;
00335 }
00336 
00337 template<class Sphere>
00338 bool NewProximityIntersection::testIntersection(Line&, Sphere&)
00339 {
00340     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Line,Sphere).\n";
00341     return true;
00342 }
00343 
00344 template<class Sphere>
00345 int NewProximityIntersection::computeIntersection(Line& e1, Sphere& e2, OutputVector* contacts)
00346 {
00347     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e2.r();
00348     int n = doIntersectionLinePoint(alarmDist*alarmDist, e1.p1(),e1.p2(), e2.center(), contacts, e2.getIndex());
00349     if (n>0)
00350     {
00351         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity() + e2.r();
00352         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00353         {
00354             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00355             detection->value -= contactDist;
00356         }
00357     }
00358     return n;
00359 }
00360 
00361 template<class Sphere>
00362 bool NewProximityIntersection::testIntersection(Triangle&, Sphere&)
00363 {
00364     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle,Sphere).\n";
00365     return true;
00366 }
00367 
00368 template<class Sphere>
00369 int NewProximityIntersection::computeIntersection(Triangle& e1, Sphere& e2, OutputVector* contacts)
00370 {
00371     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity() + e2.r();
00372     const double dist2 = alarmDist*alarmDist;
00373     int n = doIntersectionTrianglePoint(dist2, e1.flags(),e1.p1(),e1.p2(),e1.p3(),e1.n(), e2.center(), contacts, e2.getIndex());
00374     if (n>0)
00375     {
00376         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity() + e2.r();
00377         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00378         {
00379             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00380             detection->value -= contactDist;
00381         }
00382     }
00383     return n;
00384 }
00385 
00386 } // namespace collision
00387 
00388 } // namespace component
00389 
00390 } // namespace sofa
00391 
00392 #endif

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