NewProximityIntersection.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/NewProximityIntersection.inl>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <sofa/component/collision/proximity.h>
00029 #include <sofa/defaulttype/Mat.h>
00030 #include <sofa/defaulttype/Vec.h>
00031 #include <sofa/core/componentmodel/collision/Intersection.inl>
00032 #include <iostream>
00033 #include <algorithm>
00034 
00035 
00036 namespace sofa
00037 {
00038 
00039 namespace component
00040 {
00041 
00042 namespace collision
00043 {
00044 
00045 using namespace sofa::defaulttype;
00046 using namespace sofa::core::componentmodel::collision;
00047 using namespace helper;
00048 
00049 SOFA_DECL_CLASS(NewProximityIntersection)
00050 
00051 int NewProximityIntersectionClass = core::RegisterObject("Optimized Proximity Intersection based on Triangle-Triangle tests, ignoring Edge-Edge cases")
00052 .add< NewProximityIntersection >()
00053 ;
00054 
00055 NewProximityIntersection::NewProximityIntersection()
00056 : alarmDistance(initData(&alarmDistance, 1.0, "alarmDistance","Proximity detection distance"))
00057 , contactDistance(initData(&contactDistance, 0.5, "contactDistance","Distance below which a contact is created"))
00058 {
00059 }
00060 
00061 void NewProximityIntersection::init()
00062 {
00063     intersectors.add<CubeModel, CubeModel, NewProximityIntersection>(this);
00064     intersectors.add<PointModel, PointModel, NewProximityIntersection>(this);
00065     intersectors.add<SphereModel, PointModel, NewProximityIntersection>(this);
00066     intersectors.add<SphereModel, SphereModel, NewProximityIntersection>(this);
00067     intersectors.add<LineModel, PointModel, NewProximityIntersection>(this);
00068     intersectors.add<LineModel, SphereModel, NewProximityIntersection>(this);
00069     intersectors.add<LineModel, LineModel, NewProximityIntersection>(this);
00070     intersectors.add<TriangleModel, PointModel, NewProximityIntersection>(this);
00071     intersectors.add<TriangleModel, SphereModel, NewProximityIntersection>(this);
00072     intersectors.add<TriangleModel, LineModel, NewProximityIntersection>(this);
00073     intersectors.add<TriangleModel, TriangleModel, NewProximityIntersection>(this);
00074     
00075     intersectors.ignore<RayModel, PointModel>();
00076     intersectors.ignore<RayModel, LineModel>();
00077     intersectors.add<RayModel, TriangleModel, NewProximityIntersection>(this);
00078 }
00079 
00080 bool NewProximityIntersection::testIntersection(Cube &cube1, Cube &cube2)
00081 {
00082     const Vector3& minVect1 = cube1.minVect();
00083     const Vector3& minVect2 = cube2.minVect();
00084     const Vector3& maxVect1 = cube1.maxVect();
00085     const Vector3& maxVect2 = cube2.maxVect();
00086     const double alarmDist = getAlarmDistance() + cube1.getProximity() + cube2.getProximity();
00087 
00088     for (int i=0;i<3;i++)
00089     {
00090         if ( minVect1[i] > maxVect2[i] + alarmDist || minVect2[i]> maxVect1[i] + alarmDist )
00091             return false;
00092     }
00093 
00094     return true;
00095 }
00096 
00097 int NewProximityIntersection::computeIntersection(Cube&, Cube&, OutputVector* /*contacts*/)
00098 {
00099     return 0; 
00100 }
00101 
00102 bool NewProximityIntersection::testIntersection(Point& e1, Point& e2)
00103 {
00104     OutputVector contacts;
00105     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00106     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.p(), e2.p(), &contacts, -1);
00107     return n>0;
00108 }
00109 
00110 int NewProximityIntersection::computeIntersection(Point& e1, Point& e2, OutputVector* contacts)
00111 {
00112     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00113     int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.p(), e2.p(), contacts, (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex());
00114     if (n>0)
00115     {
00116         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00117         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00118         {
00119             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00120             detection->value -= contactDist;
00121         }
00122     }
00123     return n;
00124 }
00125 
00126 bool NewProximityIntersection::testIntersection(Line&, Point&)
00127 {
00128     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Line,Point).\n";
00129     return true;
00130 }
00131 
00132 int NewProximityIntersection::computeIntersection(Line& e1, Point& e2, OutputVector* contacts)
00133 {
00134     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00135     int n = doIntersectionLinePoint(alarmDist*alarmDist, e1.p1(),e1.p2(), e2.p(), contacts, e2.getIndex());
00136     if (n>0)
00137     {
00138         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00139         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00140         {
00141             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00142             detection->value -= contactDist;
00143         }
00144     }
00145     return n;
00146 }
00147 
00148 bool NewProximityIntersection::testIntersection(Line&, Line&)
00149 {
00150     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Line,Line).\n";
00151     return true;
00152 }
00153 
00154 int NewProximityIntersection::computeIntersection(Line& e1, Line& e2, OutputVector* contacts)
00155 {
00156     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00157     const double dist2 = alarmDist*alarmDist;
00158     const int id = (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex();
00159     int n = doIntersectionLineLine(dist2, e1.p1(),e1.p2(), e2.p1(),e2.p2(), contacts, id);
00160     if (n>0)
00161     {
00162         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00163         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00164         {
00165             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00166             detection->value -= contactDist;
00167         }
00168     }
00169     return n;
00170 }
00171 
00172 bool NewProximityIntersection::testIntersection(Triangle&, Point&)
00173 {
00174     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle,Point).\n";
00175     return true;
00176 }
00177 
00178 int NewProximityIntersection::computeIntersection(Triangle& e1, Point& e2, OutputVector* contacts)
00179 {
00180     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00181     const double dist2 = alarmDist*alarmDist;
00182     int n = doIntersectionTrianglePoint(dist2, e1.flags(),e1.p1(),e1.p2(),e1.p3(),e1.n(), e2.p(), contacts, e2.getIndex());
00183     if (n>0)
00184     {
00185         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00186         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00187         {
00188             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00189             detection->value -= contactDist;
00190         }
00191     }
00192     return n;
00193 }
00194 
00195 bool NewProximityIntersection::testIntersection(Triangle&, Line&)
00196 {
00197     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle& e1, Line& e2).\n";
00198     return true;
00199 }
00200 
00201 int NewProximityIntersection::computeIntersection(Triangle& e1, Line& e2, OutputVector* contacts)
00202 {
00203     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00204     const double dist2 = alarmDist*alarmDist;
00205     const Vector3& p1 = e1.p1();
00206     const Vector3& p2 = e1.p2();
00207     const Vector3& p3 = e1.p3();
00208     const Vector3& pn = e1.n();
00209     const Vector3& q1 = e2.p1();
00210     const Vector3& q2 = e2.p2();
00211 
00212     const int f1 = e1.flags();
00213 
00214     int n = 0;
00215 
00216     if (f1&TriangleModel::FLAG_P1)
00217     {
00218         n += doIntersectionLinePoint(dist2, q1,q2, p1, contacts, e2.getIndex(), true);
00219     }
00220     if (f1&TriangleModel::FLAG_P2)
00221     {
00222         n += doIntersectionLinePoint(dist2, q1,q2, p2, contacts, e2.getIndex(), true);
00223     }
00224     if (f1&TriangleModel::FLAG_P3)
00225     {
00226         n += doIntersectionLinePoint(dist2, q1,q2, p3, contacts, e2.getIndex(), true);
00227     }
00228 
00229     n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q1, contacts, e2.getIndex(), false);
00230     n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q2, contacts, e2.getIndex(), false);
00231 
00232     if (n>0)
00233     {
00234         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00235         for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00236         {
00237             detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00238             detection->value -= contactDist;
00239         }
00240     }
00241     return n;
00242 }
00243 
00244 
00245 bool NewProximityIntersection::testIntersection(Triangle&, Triangle&)
00246 {
00247     std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle& e1, Triangle& e2).\n";
00248     return true;
00249 }
00250 
00251 int NewProximityIntersection::computeIntersection(Triangle& e1, Triangle& e2, OutputVector* contacts)
00252 {
00253     if (e1.getIndex() >= e1.getCollisionModel()->getSize())
00254     {
00255         std::cerr << "NewProximityIntersection::computeIntersection(Triangle, Triangle): ERROR invalid e1 index "<<e1.getIndex()<<" on CM "<<e1.getCollisionModel()->getName()<<" of size "<<e1.getCollisionModel()->getSize()<<std::endl;
00256         return 0;
00257     }
00258     if (e2.getIndex() >= e2.getCollisionModel()->getSize())
00259     {
00260         std::cerr << "NewProximityIntersection::computeIntersection(Triangle, Triangle): ERROR invalid e2 index "<<e2.getIndex()<<" on CM "<<e2.getCollisionModel()->getName()<<" of size "<<e2.getCollisionModel()->getSize()<<std::endl;
00261         return 0;
00262     }
00263     const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00264     const double dist2 = alarmDist*alarmDist;
00265     const Vector3& p1 = e1.p1();
00266     const Vector3& p2 = e1.p2();
00267     const Vector3& p3 = e1.p3();
00268     const Vector3& pn = e1.n();
00269     const Vector3& q1 = e2.p1();
00270     const Vector3& q2 = e2.p2();
00271     const Vector3& q3 = e2.p3();
00272     const Vector3& qn = e2.n();
00273 
00274     const int f1 = e1.flags();
00275     const int f2 = e2.flags();
00276 
00277     const int id1 = e1.getIndex()*3; // index of contacts involving points in e1
00278     const int id2 = e1.getCollisionModel()->getSize()*3 + e2.getIndex()*3; // index of contacts involving points in e2
00279 
00280     int n = 0;
00281 
00282     if (f1&TriangleModel::FLAG_P1)
00283         n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p1, contacts, id1+0, true);
00284     if (f1&TriangleModel::FLAG_P2)
00285         n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p2, contacts, id1+1, true);
00286     if (f1&TriangleModel::FLAG_P3)
00287         n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p3, contacts, id1+2, true);
00288 
00289     if (f2&TriangleModel::FLAG_P1)
00290         n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q1, contacts, id2+0, false);
00291     if (f2&TriangleModel::FLAG_P2)
00292         n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q2, contacts, id2+1, false);
00293     if (f2&TriangleModel::FLAG_P3)
00294         n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q3, contacts, id2+2, false);
00295 
00296     if (n>0)
00297     {
00298         const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00299 //        for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00300         for (int i=0;i<n;++i)
00301         {
00302             //detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00303             //detection->value -= contactDist;
00304             (*contacts)[contacts->size()-n+i].elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00305             (*contacts)[contacts->size()-n+i].value -= contactDist;
00306 
00307         }
00308     }
00309     return n;
00310 }
00311 
00312 
00313 bool NewProximityIntersection::testIntersection(Ray &t1,Triangle &t2)
00314 {
00315     Vector3 P,Q,PQ;
00316     static DistanceSegTri proximitySolver;
00317     const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00318 
00319     if (fabs(t2.n() * t1.direction()) < 0.000001)
00320         return false; // no intersection for edges parallel to the triangle
00321 
00322     Vector3 A = t1.origin();
00323     Vector3 B = A + t1.direction() * t1.l();
00324 
00325     proximitySolver.NewComputation( &t2, A, B,P,Q);
00326     PQ = Q-P;
00327 
00328     if (PQ.norm2() < alarmDist*alarmDist)
00329     {
00330         //std::cout<<"Collision between Line - Triangle"<<std::endl;
00331         return true;
00332     }
00333     else
00334         return false;
00335 }
00336 
00337 int NewProximityIntersection::computeIntersection(Ray &t1, Triangle &t2, OutputVector* contacts)
00338 {
00339     const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00340 
00341     if (fabs(t2.n() * t1.direction()) < 0.000001)
00342         return false; // no intersection for edges parallel to the triangle
00343 
00344     Vector3 A = t1.origin();
00345     Vector3 B = A + t1.direction() * t1.l();
00346 
00347     Vector3 P,Q,PQ;
00348     static DistanceSegTri proximitySolver;
00349 
00350     proximitySolver.NewComputation( &t2, A,B,P,Q);
00351     PQ = Q-P;
00352 
00353     if (PQ.norm2() >= alarmDist*alarmDist)
00354         return 0;
00355 
00356     const double contactDist = alarmDist;
00357     contacts->resize(contacts->size()+1);
00358     DetectionOutput *detection = &*(contacts->end()-1);
00359 
00360     detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(t1, t2);
00361     detection->point[1]=P;
00362     detection->point[0]=Q;
00363 #ifdef DETECTIONOUTPUT_FREEMOTION
00364     detection->freePoint[1] = P;
00365     detection->freePoint[0] = Q;
00366 #endif
00367     detection->normal=-t2.n();
00368     detection->value = PQ.norm();
00369     detection->value -= contactDist;
00370     return 1;
00371 }
00372 
00373 } // namespace collision
00374 
00375 } // namespace component
00376 
00377 } // namespace sofa
00378 

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