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 #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
00073
00074
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
00089 contacts->resize(contacts->size()+1);
00090 DetectionOutput *detection = &*(contacts->end()-1);
00091
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
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
00114 {
00115 alpha = b/A;
00116
00117
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
00129 contacts->resize(contacts->size()+1);
00130 DetectionOutput *detection = &*(contacts->end()-1);
00131
00132
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
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
00160 contacts->resize(contacts->size()+1);
00161 DetectionOutput *detection = &*(contacts->end()-1);
00162
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
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& , 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
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
00195
00196
00197
00198 if (alpha < 0.000001 || beta < 0.000001 || alpha + beta > 0.999999)
00199 {
00200
00201 double pAB = b[0] / A[0][0];
00202
00203 double pAC = b[1] / A[1][1];
00204 if (pAB < 0.000001 && pAC < 0.0000001)
00205 {
00206 if (!(flags&TriangleModel::FLAG_P1)) return 0;
00207 alpha = 0.0;
00208 beta = 0.0;
00209 }
00210 else if (pAB < 0.999999 && beta < 0.000001)
00211 {
00212 if (!(flags&TriangleModel::FLAG_E12)) return 0;
00213 alpha = pAB;
00214 beta = 0.0;
00215 }
00216 else if (pAC < 0.999999 && alpha < 0.000001)
00217 {
00218 if (!(flags&TriangleModel::FLAG_E12)) return 0;
00219 alpha = 0.0;
00220 beta = pAC;
00221 }
00222 else
00223 {
00224
00225
00226 double pBC = (b[1] - b[0] + A[0][0] - A[1][1]) / (A[0][0] + A[1][1] - 2*A[0][1]);
00227 if (pBC < 0.000001)
00228 {
00229 if (!(flags&TriangleModel::FLAG_P2)) return 0;
00230 alpha = 1.0;
00231 beta = 0.0;
00232 }
00233 else if (pBC > 0.999999)
00234 {
00235 if (!(flags&TriangleModel::FLAG_P3)) return 0;
00236 alpha = 0.0;
00237 beta = 1.0;
00238 }
00239 else
00240 {
00241 if (!(flags&TriangleModel::FLAG_E31)) return 0;
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
00256 contacts->resize(contacts->size()+1);
00257 DetectionOutput *detection = &*(contacts->end()-1);
00258
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
00276
00277
00278
00279
00280
00281
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 }
00387
00388 }
00389
00390 }
00391
00392 #endif