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_TOPOLOGY_TRIANGLESETGEOMETRYALGORITHMS_INL
00026 #define SOFA_COMPONENT_TOPOLOGY_TRIANGLESETGEOMETRYALGORITHMS_INL
00027
00028 #include <sofa/component/topology/TriangleSetGeometryAlgorithms.h>
00029
00030 namespace sofa
00031 {
00032
00033 namespace component
00034 {
00035
00036 namespace topology
00037 {
00038 using namespace sofa::defaulttype;
00039
00040 template< class DataTypes>
00041 typename DataTypes::Real TriangleSetGeometryAlgorithms< DataTypes >::computeTriangleArea( const unsigned int i) const
00042 {
00043 const Triangle &t = this->m_topology->getTriangle(i);
00044 const VecCoord& p = *(this->object->getX());
00045 Real area = (Real)(areaProduct(p[t[1]]-p[t[0]], p[t[2]]-p[t[0]]) * 0.5);
00046 return area;
00047 }
00048
00049 template< class DataTypes>
00050 typename DataTypes::Real TriangleSetGeometryAlgorithms< DataTypes >::computeRestTriangleArea( const unsigned int i) const
00051 {
00052 const Triangle &t = this->m_topology->getTriangle(i);
00053 const VecCoord& p = *(this->object->getX0());
00054 Real area = (Real) (areaProduct(p[t[1]]-p[t[0]],p[t[2]]-p[t[0]]) * 0.5);
00055 return area;
00056 }
00057
00059 template<class DataTypes>
00060 void TriangleSetGeometryAlgorithms<DataTypes>::computeTriangleArea( BasicArrayInterface<Real> &ai) const
00061 {
00062 const sofa::helper::vector<Triangle> &ta = this->m_topology->getTriangles();
00063 const typename DataTypes::VecCoord& p = *(this->object->getX());
00064
00065 for (unsigned int i=0; i<ta.size(); ++i)
00066 {
00067 const Triangle &t=ta[i];
00068 ai[i]=(Real)(areaProduct(p[t[1]]-p[t[0]],p[t[2]]-p[t[0]])/2.0);
00069 }
00070 }
00071
00072
00073 template<class DataTypes>
00074 Vec<3,double> TriangleSetGeometryAlgorithms< DataTypes >::computeBaryEdgePoint(sofa::helper::vector< unsigned int>& indices,
00075 const double &coord_p)
00076 {
00077 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00078
00079 const typename DataTypes::Coord& c1 = vect_c[indices[0]];
00080 const typename DataTypes::Coord& c2 = vect_c[indices[1]];
00081
00082 Vec<3,Real> p;
00083 p[0] = (Real) ((1.0-coord_p)*c1[0] + coord_p*c2[0]);
00084 p[1] = (Real) ((1.0-coord_p)*c1[1] + coord_p*c2[1]);
00085 p[2] = (Real) ((1.0-coord_p)*c1[2] + coord_p*c2[2]);
00086
00087 return ((Vec<3,double>) p);
00088 }
00089
00090
00091 template<class DataTypes>
00092 Vec<3,double> TriangleSetGeometryAlgorithms< DataTypes >::getOppositePoint(unsigned int ind_p,
00093 sofa::helper::vector< unsigned int>& indices,
00094 const double &coord_p)
00095 {
00096 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00097
00098 const typename DataTypes::Coord& c1 = vect_c[indices[0]];
00099 const typename DataTypes::Coord& c2 = vect_c[indices[1]];
00100
00101 Vec<3,Real> p;
00102
00103 if(ind_p == indices[0])
00104 {
00105 p[0]= (Real) c2[0];
00106 p[1]= (Real) c2[1];
00107 p[2]= (Real) c2[2];
00108 }
00109 else
00110 {
00111 if(ind_p == indices[1])
00112 {
00113 p[0]= (Real) c1[0];
00114 p[1]= (Real) c1[1];
00115 p[2]= (Real) c1[2];
00116 }
00117 else
00118 {
00119 p[0]= (Real) ((1.0-coord_p)*c1[0] + coord_p*c2[0]);
00120 p[1]= (Real) ((1.0-coord_p)*c1[1] + coord_p*c2[1]);
00121 p[2]= (Real) ((1.0-coord_p)*c1[2] + coord_p*c2[2]);
00122 }
00123 }
00124
00125 return ((Vec<3,double>) p);
00126 }
00127
00128
00129 template<class DataTypes>
00130 Vec<3,double> TriangleSetGeometryAlgorithms< DataTypes >::computeTriangleNormal(const unsigned int ind_t)
00131 {
00132 const Triangle &t = this->m_topology->getTriangle(ind_t);
00133 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00134
00135 const typename DataTypes::Coord& c0 = vect_c[t[0]];
00136 const typename DataTypes::Coord& c1 = vect_c[t[1]];
00137 const typename DataTypes::Coord& c2 = vect_c[t[2]];
00138
00139 Vec<3,Real> p0;
00140 p0[0] = (Real) (c0[0]);
00141 p0[1] = (Real) (c0[1]);
00142 p0[2] = (Real) (c0[2]);
00143 Vec<3,Real> p1;
00144 p1[0] = (Real) (c1[0]);
00145 p1[1] = (Real) (c1[1]);
00146 p1[2] = (Real) (c1[2]);
00147 Vec<3,Real> p2;
00148 p2[0] = (Real) (c2[0]);
00149 p2[1] = (Real) (c2[1]);
00150 p2[2] = (Real) (c2[2]);
00151
00152 Vec<3,Real> normal_t=(p1-p0).cross( p2-p0);
00153
00154 return ((Vec<3,double>) normal_t);
00155 }
00156
00157
00158 template<class DataTypes>
00159 sofa::helper::vector< double > TriangleSetGeometryAlgorithms< DataTypes >::computeTriangleBarycoefs( const Vec<3,
00160 double> &p,
00161 unsigned int ind_t)
00162 {
00163 sofa::helper::vector< double > baryCoefs;
00164
00165 const Triangle &t=this->m_topology->getTriangle(ind_t);
00166 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00167
00168 const typename DataTypes::Coord& c0=vect_c[t[0]];
00169 const typename DataTypes::Coord& c1=vect_c[t[1]];
00170 const typename DataTypes::Coord& c2=vect_c[t[2]];
00171
00172 Vec<3,Real> a;
00173 a[0] = (Real) (c0[0]);
00174 a[1] = (Real) (c0[1]);
00175 a[2] = (Real) (c0[2]);
00176 Vec<3,Real> b;
00177 b[0] = (Real) (c1[0]);
00178 b[1] = (Real) (c1[1]);
00179 b[2] = (Real) (c1[2]);
00180 Vec<3,Real> c;
00181 c[0] = (Real) (c2[0]);
00182 c[1] = (Real) (c2[1]);
00183 c[2] = (Real) (c2[2]);
00184
00185 Vec<3,double> M = (Vec<3,double>) (b-a).cross(c-a);
00186 double norm2_M = M*(M);
00187
00188 double coef_a, coef_b, coef_c;
00189
00190 if(norm2_M==0.0)
00191 {
00192 coef_a = (double) (1.0/3.0);
00193 coef_b = (double) (1.0/3.0);
00194 coef_c = (double) (1.0 - (coef_a + coef_b));
00195 }
00196 else
00197 {
00198 Vec<3,Real> N = M/norm2_M;
00199
00200 coef_a = N*((b-p).cross(c-p));
00201 coef_b = N*((c-p).cross(a-p));
00202 coef_c = (double) (1.0 - (coef_a + coef_b));
00203 }
00204
00205 baryCoefs.push_back(coef_a);
00206 baryCoefs.push_back(coef_b);
00207 baryCoefs.push_back(coef_c);
00208
00209 return baryCoefs;
00210 }
00211
00212
00213 template<class DataTypes>
00214 sofa::helper::vector< double > TriangleSetGeometryAlgorithms< DataTypes >::compute3PointsBarycoefs( const Vec<3,
00215 double> &p,
00216 unsigned int ind_p1,
00217 unsigned int ind_p2,
00218 unsigned int ind_p3)
00219 {
00220 sofa::helper::vector< double > baryCoefs;
00221
00222 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00223
00224 const typename DataTypes::Coord& c0 = vect_c[ind_p1];
00225 const typename DataTypes::Coord& c1 = vect_c[ind_p2];
00226 const typename DataTypes::Coord& c2 = vect_c[ind_p3];
00227
00228 Vec<3,Real> a;
00229 a[0] = (Real) (c0[0]);
00230 a[1] = (Real) (c0[1]);
00231 a[2] = (Real) (c0[2]);
00232 Vec<3,Real> b;
00233 b[0] = (Real) (c1[0]);
00234 b[1] = (Real) (c1[1]);
00235 b[2] = (Real) (c1[2]);
00236 Vec<3,Real> c;
00237 c[0] = (Real) (c2[0]);
00238 c[1] = (Real) (c2[1]);
00239 c[2] = (Real) (c2[2]);
00240
00241 Vec<3,double> M = (Vec<3,double>) (b-a).cross(c-a);
00242 double norm2_M = M*(M);
00243
00244 double coef_a, coef_b, coef_c;
00245
00246 if(norm2_M==0.0)
00247 {
00248 coef_a = (double) (1.0/3.0);
00249 coef_b = (double) (1.0/3.0);
00250 coef_c = (double) (1.0 - (coef_a + coef_b));
00251 }
00252 else
00253 {
00254 Vec<3,Real> N = M/norm2_M;
00255
00256 coef_a = N*((b-p).cross(c-p));
00257 coef_b = N*((c-p).cross(a-p));
00258 coef_c = (double) (1.0 - (coef_a + coef_b));
00259 }
00260
00261 baryCoefs.push_back(coef_a);
00262 baryCoefs.push_back(coef_b);
00263 baryCoefs.push_back(coef_c);
00264
00265 return baryCoefs;
00266 }
00267
00268
00269 template<class DataTypes>
00270 void TriangleSetGeometryAlgorithms< DataTypes >::closestIndexPair(unsigned int ind_ta, unsigned int ind_tb,
00271 unsigned int &ind1, unsigned int &ind2)
00272 {
00273 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00274
00275 const Triangle &ta=this->m_topology->getTriangle(ind_ta);
00276 const Triangle &tb=this->m_topology->getTriangle(ind_tb);
00277
00278 Real min_value=(Real) 0.0;
00279 bool is_init = false;
00280
00281 for(unsigned int i=0; i<3; i++)
00282 {
00283 const typename DataTypes::Coord& ca=vect_c[ta[i]];
00284 Vec<3,Real> pa;
00285 pa[0] = (Real) (ca[0]);
00286 pa[1] = (Real) (ca[1]);
00287 pa[2] = (Real) (ca[2]);
00288
00289 for(unsigned int j=0; j!=i && j<3; j++)
00290 {
00291 const typename DataTypes::Coord& cb=vect_c[tb[i]];
00292 Vec<3,Real> pb;
00293 pb[0] = (Real) (cb[0]);
00294 pb[1] = (Real) (cb[1]);
00295 pb[2] = (Real) (cb[2]);
00296
00297 Real norm_v_normal = (pa-pb)*(pa-pb);
00298 if(!is_init)
00299 {
00300 min_value = norm_v_normal;
00301 ind1 = ta[i];
00302 ind2 = tb[j];
00303 is_init = true;
00304 }
00305 else
00306 {
00307 if(norm_v_normal<min_value)
00308 {
00309 min_value = norm_v_normal;
00310 ind1 = ta[i];
00311 ind2 = tb[j];
00312 }
00313 }
00314 }
00315 }
00316
00317 return;
00318 }
00319
00320
00321 template<class DataTypes>
00322 bool TriangleSetGeometryAlgorithms< DataTypes >::is_PointinTriangle(bool is_tested, const Vec<3,Real>& p,
00323 unsigned int ind_t, unsigned int &ind_t_test)
00324 {
00325 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00326 const Triangle &t=this->m_topology->getTriangle(ind_t);
00327
00328 const typename DataTypes::Coord& c0=vect_c[t[0]];
00329 const typename DataTypes::Coord& c1=vect_c[t[1]];
00330 const typename DataTypes::Coord& c2=vect_c[t[2]];
00331
00332 Vec<3,Real> ptest = p;
00333
00334 Vec<3,Real> p0;
00335 p0[0] = (Real) (c0[0]);
00336 p0[1] = (Real) (c0[1]);
00337 p0[2] = (Real) (c0[2]);
00338 Vec<3,Real> p1;
00339 p1[0] = (Real) (c1[0]);
00340 p1[1] = (Real) (c1[1]);
00341 p1[2] = (Real) (c1[2]);
00342 Vec<3,Real> p2;
00343 p2[0] = (Real) (c2[0]);
00344 p2[1] = (Real) (c2[1]);
00345 p2[2] = (Real) (c2[2]);
00346
00347 Vec<3,Real> v_normal = (p2-p0).cross(p1-p0);
00348
00349 Real norm_v_normal = v_normal*(v_normal);
00350 if(norm_v_normal != 0.0)
00351 {
00352 Vec<3,Real> n_01 = (p1-p0).cross(v_normal);
00353 Vec<3,Real> n_12 = (p2-p1).cross(v_normal);
00354 Vec<3,Real> n_20 = (p0-p2).cross(v_normal);
00355
00356 double v_01 = (double) ((ptest-p0)*(n_01));
00357 double v_12 = (double) ((ptest-p1)*(n_12));
00358 double v_20 = (double) ((ptest-p2)*(n_20));
00359
00360 bool is_inside = (v_01 > 0.0) && (v_12 > 0.0) && (v_20 > 0.0);
00361
00362 if(is_tested && (!is_inside))
00363 {
00364 sofa::helper::vector< unsigned int > shell;
00365 unsigned int ind_edge = 0;
00366
00367 if(v_01 < 0.0)
00368 {
00369 if(v_12 < 0.0)
00370 {
00371 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleVertexShell(t[1]));
00372 }
00373 else
00374 {
00375 if(v_20 < 0.0)
00376 {
00377 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleVertexShell(t[0]));
00378
00379 }
00380 else
00381 {
00382 ind_edge=this->m_topology->getEdgeIndex(t[0],t[1]);
00383 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
00384 }
00385 }
00386 }
00387 else
00388 {
00389 if(v_12 < 0.0)
00390 {
00391 if(v_20 < 0.0)
00392 {
00393 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleVertexShell(t[2]));
00394
00395 }
00396 else
00397 {
00398 ind_edge=this->m_topology->getEdgeIndex(t[1],t[2]);
00399 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
00400 }
00401 }
00402 else
00403 {
00404 ind_edge=this->m_topology->getEdgeIndex(t[2],t[0]);
00405 shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
00406 }
00407 }
00408
00409 unsigned int i =0;
00410 bool is_in_next_triangle=false;
00411 unsigned int ind_triangle=0;
00412 unsigned ind_t_false_init;
00413 unsigned int &ind_t_false = ind_t_false_init;
00414
00415 if(shell.size()>1)
00416 {
00417 while(i < shell.size() && !is_in_next_triangle)
00418 {
00419 ind_triangle=shell[i];
00420
00421 if(ind_triangle != ind_t)
00422 {
00423 is_in_next_triangle = is_PointinTriangle(false, p, ind_triangle, ind_t_false);
00424 }
00425 i++;
00426 }
00427
00428 if(is_in_next_triangle)
00429 {
00430 ind_t_test=ind_triangle;
00431
00432 }
00433 else
00434 {
00435
00436 ind_t_test=ind_t;
00437 }
00438 }
00439 else
00440 {
00441 ind_t_test=ind_t;
00442 }
00443 }
00444 return is_inside;
00445
00446 }
00447 else
00448 {
00449
00450 return false;
00451 }
00452 }
00453
00454
00455 template<class DataTypes>
00456 bool TriangleSetGeometryAlgorithms< DataTypes >::isQuadDeulaunayOriented(const Vec<3,double>& p_q1,
00457 const Vec<3,double>& p_q2,
00458 unsigned int ind_q3,
00459 unsigned int ind_q4)
00460 {
00461 sofa::helper::vector< double > baryCoefs;
00462
00463 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00464
00465 const typename DataTypes::Coord& c3 = vect_c[ind_q3];
00466 const typename DataTypes::Coord& c4 = vect_c[ind_q4];
00467
00468 Vec<3,Real> q1 = (Vec<3,Real>) p_q1;
00469 Vec<3,Real> q2 = (Vec<3,Real>) p_q2;
00470
00471 Vec<3,Real> q3;
00472 q3[0] = (Real) (c3[0]);
00473 q3[1] = (Real) (c3[1]);
00474 q3[2] = (Real) (c3[2]);
00475 Vec<3,Real> q4;
00476 q4[0] = (Real) (c4[0]);
00477 q4[1] = (Real) (c4[1]);
00478 q4[2] = (Real) (c4[2]);
00479
00480 Vec<3,Real> G = (q1+q2+q3)/3.0;
00481
00482 if((G-q2)*(G-q2) <= (G-q4)*(G-q4))
00483 {
00484 return true;
00485 }
00486 else
00487 {
00488 return false;
00489 }
00490 }
00491
00492
00493 template<class DataTypes>
00494 bool TriangleSetGeometryAlgorithms< DataTypes >::is_triangle_in_plane(const unsigned int ind_t, const unsigned int ind_p, const Vec<3,Real>&plane_vect)
00495 {
00496 const Triangle &t=this->m_topology->getTriangle(ind_t);
00497
00498
00499
00500 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00501
00502 unsigned int ind_1;
00503 unsigned int ind_2;
00504
00505 if(ind_p==t[0])
00506 {
00507 ind_1=t[1];
00508 ind_2=t[2];
00509 }
00510 else
00511 {
00512 if(ind_p==t[1])
00513 {
00514 ind_1=t[2];
00515 ind_2=t[0];
00516 }
00517 else
00518 {
00519 ind_1=t[0];
00520 ind_2=t[1];
00521 }
00522 }
00523
00524 const typename DataTypes::Coord& c0=vect_c[ind_p];
00525 const typename DataTypes::Coord& c1=vect_c[ind_1];
00526 const typename DataTypes::Coord& c2=vect_c[ind_2];
00527
00528 Vec<3,Real> p0;
00529 p0[0] = (Real) (c0[0]);
00530 p0[1] = (Real) (c0[1]);
00531 p0[2] = (Real) (c0[2]);
00532 Vec<3,Real> p1;
00533 p1[0] = (Real) (c1[0]);
00534 p1[1] = (Real) (c1[1]);
00535 p1[2] = (Real) (c1[2]);
00536 Vec<3,Real> p2;
00537 p2[0] = (Real) (c2[0]);
00538 p2[1] = (Real) (c2[1]);
00539 p2[2] = (Real) (c2[2]);
00540
00541 return((p1-p0)*( plane_vect)>=0.0 && (p1-p0)*( plane_vect)>=0.0);
00542 }
00543
00544
00545 template<class DataTypes>
00546 void TriangleSetGeometryAlgorithms< DataTypes >::Prepare_VertexDuplication(const unsigned int ind_p,
00547 const unsigned int ind_t_from,
00548 const unsigned int ind_t_to,
00549 const sofa::helper::vector< unsigned int>& indices_from,
00550 const double &coord_from,
00551 const sofa::helper::vector< unsigned int>& indices_to,
00552 const double &coord_to,
00553 sofa::helper::vector< unsigned int > &triangles_list_1,
00554 sofa::helper::vector< unsigned int > &triangles_list_2)
00555 {
00556
00557
00558 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00559
00560 const typename DataTypes::Coord& c_p = vect_c[ind_p];
00561 Vec<3,Real> point_p;
00562 point_p[0]= (Real) c_p[0];
00563 point_p[1]= (Real) c_p[1];
00564 point_p[2]= (Real) c_p[2];
00565
00566 Vec<3,Real> point_from=(Vec<3,Real>) getOppositePoint(ind_p, (sofa::helper::vector< unsigned int>&) indices_from, coord_from);
00567 Vec<3,Real> point_to=(Vec<3,Real>) getOppositePoint(ind_p, (sofa::helper::vector< unsigned int>&) indices_to, coord_to);
00568
00569
00570
00571
00572 Vec<3,Real> vect_from = point_from - point_p;
00573 Vec<3,Real> vect_to = point_p - point_to;
00574
00575
00576
00577
00578 Vec<3,Real> normal_from;
00579 Vec<3,Real> normal_to;
00580
00581 Vec<3,Real> plane_from;
00582 Vec<3,Real> plane_to;
00583
00584 if((coord_from!=0.0) && (coord_from!=1.0))
00585 {
00586 normal_from=(Vec<3,Real>) computeTriangleNormal(ind_t_from);
00587 plane_from=vect_from.cross( normal_from);
00588 }
00589 else
00590 {
00591
00592
00593 unsigned int ind_edge;
00594
00595 if(coord_from==0.0)
00596 {
00597 ind_edge=this->m_topology->getEdgeIndex(indices_from[0], ind_p);
00598 }
00599 else
00600 {
00601 ind_edge=this->m_topology->getEdgeIndex(indices_from[1], ind_p);
00602 }
00603
00604 if (this->m_topology->getNbEdges()>0)
00605 {
00606 sofa::helper::vector< unsigned int > shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
00607 unsigned int ind_triangle=shell[0];
00608 unsigned int i=0;
00609 bool is_in_next_triangle=false;
00610
00611 if(shell.size()>1)
00612 {
00613 while(i < shell.size() || !is_in_next_triangle)
00614 {
00615 if(shell[i] != ind_t_from)
00616 {
00617 ind_triangle=shell[i];
00618 is_in_next_triangle=true;
00619 }
00620 i++;
00621 }
00622 }
00623 else
00624 {
00625 return;
00626 }
00627
00628 if(is_in_next_triangle)
00629 {
00630 Vec<3,Real> normal_from_1=(Vec<3,Real>) computeTriangleNormal(ind_triangle);
00631 Vec<3,Real> normal_from_2=(Vec<3,Real>) computeTriangleNormal(ind_t_from);
00632
00633 normal_from=(normal_from_1+normal_from_2)/2.0;
00634 plane_from=vect_from.cross( normal_from);
00635 }
00636 else
00637 {
00638 return;
00639 }
00640 }
00641 }
00642
00643 if((coord_to!=0.0) && (coord_to!=1.0))
00644 {
00645 normal_to=(Vec<3,Real>) computeTriangleNormal(ind_t_to);
00646
00647 plane_to=vect_to.cross( normal_to);
00648 }
00649 else
00650 {
00651
00652
00653 unsigned int ind_edge;
00654
00655 if(coord_to==0.0)
00656 {
00657 ind_edge=this->m_topology->getEdgeIndex(indices_to[0], ind_p);
00658 }
00659 else
00660 {
00661 ind_edge=this->m_topology->getEdgeIndex(indices_to[1], ind_p);
00662 }
00663
00664 if (this->m_topology->getNbEdges()>0)
00665 {
00666 sofa::helper::vector< unsigned int > shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
00667 unsigned int ind_triangle=shell[0];
00668 unsigned int i=0;
00669 bool is_in_next_triangle=false;
00670
00671 if(shell.size()>1)
00672 {
00673 while(i < shell.size() || !is_in_next_triangle)
00674 {
00675 if(shell[i] != ind_t_to)
00676 {
00677 ind_triangle=shell[i];
00678 is_in_next_triangle=true;
00679 }
00680 i++;
00681 }
00682 }
00683 else
00684 {
00685 return;
00686 }
00687
00688 if(is_in_next_triangle)
00689 {
00690 Vec<3,Real> normal_to_1=(Vec<3,Real>) computeTriangleNormal(ind_triangle);
00691 Vec<3,Real> normal_to_2=(Vec<3,Real>) computeTriangleNormal(ind_t_to);
00692
00693 normal_to=(normal_to_1+normal_to_2)/2.0;
00694 plane_to=vect_to.cross( normal_to);
00695 }
00696 else
00697 {
00698 return;
00699 }
00700 }
00701 }
00702
00703 if (this->m_topology->getNbPoints()>0)
00704 {
00705 sofa::helper::vector< unsigned int > shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleVertexShell(ind_p));
00706 unsigned int ind_triangle=shell[0];
00707 unsigned int i=0;
00708
00709 bool is_in_plane_from;
00710 bool is_in_plane_to;
00711
00712 if(shell.size()>1)
00713 {
00714 Vec<3,Real> normal_test = plane_from.cross( plane_to);
00715 Real value_test = normal_test*(normal_from+normal_to);
00716
00717 if(value_test<=0.0)
00718 {
00719
00720
00721
00722 while(i < shell.size())
00723 {
00724 ind_triangle=shell[i];
00725
00726 is_in_plane_from=is_triangle_in_plane(ind_triangle,ind_p, (const Vec<3,double>&) plane_from);
00727 is_in_plane_to=is_triangle_in_plane(ind_triangle,ind_p, (const Vec<3,double>&) plane_to);
00728
00729 if((ind_triangle != ind_t_from) && (ind_triangle != ind_t_to))
00730 {
00731 if(is_in_plane_from || is_in_plane_to)
00732 {
00733 triangles_list_1.push_back(ind_triangle);
00734 }
00735 else
00736 {
00737 triangles_list_2.push_back(ind_triangle);
00738 }
00739 }
00740 i++;
00741 }
00742 }
00743 else
00744 {
00745
00746
00747
00748 while(i < shell.size())
00749 {
00750 ind_triangle=shell[i];
00751
00752 is_in_plane_from=is_triangle_in_plane(ind_triangle,ind_p, (const Vec<3,double>&) plane_from);
00753 is_in_plane_to=is_triangle_in_plane(ind_triangle,ind_p, (const Vec<3,double>&) plane_to);
00754
00755 if((ind_triangle != ind_t_from) && (ind_triangle != ind_t_to))
00756 {
00757 if(is_in_plane_from && is_in_plane_to)
00758 {
00759 triangles_list_1.push_back(ind_triangle);
00760 }
00761 else
00762 {
00763 triangles_list_2.push_back(ind_triangle);
00764 }
00765 }
00766 i++;
00767 }
00768 }
00769 }
00770 else
00771 {
00772 return;
00773 }
00774 }
00775 else
00776 {
00777 return;
00778 }
00779 }
00780
00781 template<class DataTypes>
00782 const typename DataTypes::Coord& TriangleSetGeometryAlgorithms< DataTypes >::getPositionPoint(unsigned int i)
00783 {
00784 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00785 return vect_c[i];
00786 }
00787
00788
00789 template<class DataTypes>
00790 bool TriangleSetGeometryAlgorithms< DataTypes >::computeSegmentTriangleIntersection(bool is_entered,
00791 const Vec<3,double>& a,
00792 const Vec<3,double>& b,
00793 const unsigned int ind_t,
00794 sofa::helper::vector<unsigned int> &indices,
00795 double &baryCoef, double& coord_kmin)
00796 {
00797
00798
00799
00800 unsigned int ind_first=0;
00801 unsigned int ind_second=0;
00802
00803 if(indices.size()>1)
00804 {
00805 ind_first=indices[0];
00806 ind_second=indices[1];
00807 }
00808
00809 indices.clear();
00810
00811 bool is_validated = false;
00812 bool is_intersected = false;
00813
00814 const Triangle &t=this->m_topology->getTriangle(ind_t);
00815 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
00816
00817 bool is_full_01=(is_entered && ((t[0] == ind_first && t[1] == ind_second) || (t[1] == ind_first && t[0] == ind_second)));
00818 bool is_full_12=(is_entered && ((t[1] == ind_first && t[2] == ind_second) || (t[2] == ind_first && t[1] == ind_second)));
00819 bool is_full_20=(is_entered && ((t[2] == ind_first && t[0] == ind_second) || (t[0] == ind_first && t[2] == ind_second)));
00820
00821 const typename DataTypes::Coord& c0=vect_c[t[0]];
00822 const typename DataTypes::Coord& c1=vect_c[t[1]];
00823 const typename DataTypes::Coord& c2=vect_c[t[2]];
00824
00825 Vec<3,Real> p0;
00826 p0[0] = (Real) (c0[0]);
00827 p0[1] = (Real) (c0[1]);
00828 p0[2] = (Real) (c0[2]);
00829 Vec<3,Real> p1;
00830 p1[0] = (Real) (c1[0]);
00831 p1[1] = (Real) (c1[1]);
00832 p1[2] = (Real) (c1[2]);
00833 Vec<3,Real> p2;
00834 p2[0] = (Real) (c2[0]);
00835 p2[1] = (Real) (c2[1]);
00836 p2[2] = (Real) (c2[2]);
00837
00838 Vec<3,Real> pa;
00839 pa[0] = (Real) (a[0]);
00840 pa[1] = (Real) (a[1]);
00841 pa[2] = (Real) (a[2]);
00842 Vec<3,Real> pb;
00843 pb[0] = (Real) (b[0]);
00844 pb[1] = (Real) (b[1]);
00845 pb[2] = (Real) (b[2]);
00846
00847 Vec<3,Real> v_normal = (p2-p0).cross(p1-p0);
00848
00849
00850 Real norm_v_normal = v_normal.norm();
00851
00852 if(norm_v_normal != 0.0)
00853 {
00854 v_normal/=norm_v_normal;
00855
00856 Vec<3,Real> v_ab = pb-pa;
00857 Vec<3,Real> v_ab_proj = v_ab - v_ab.linearProduct(v_normal).linearProduct(v_normal);
00858 Vec<3,Real> pb_proj = v_ab_proj + pa;
00859
00860 Vec<3,Real> v_01 = p1-p0;
00861 Vec<3,Real> v_12 = p2-p1;
00862 Vec<3,Real> v_20 = p0-p2;
00863
00864 Vec<3,Real> n_proj =v_ab_proj.cross(v_normal);
00865 Vec<3,Real> n_01 = v_01.cross(v_normal);
00866 Vec<3,Real> n_12 = v_12.cross(v_normal);
00867 Vec<3,Real> n_20 = v_20.cross(v_normal);
00868
00869 Real norm2_v_ab_proj = v_ab_proj*(v_ab_proj);
00870
00871 if(norm2_v_ab_proj != 0.0)
00872 {
00873 double init_t=0.0;
00874 double init_k=0.0;
00875 double init_kmin=0.0;
00876
00877 double& coord_t=init_t;
00878 double& coord_k=init_k;
00879
00880 double is_initialized=false;
00881 coord_kmin=init_kmin;
00882
00883 double coord_test1;
00884 double coord_test2;
00885
00886 double s_t;
00887 double s_k;
00888
00889 if(!is_full_01)
00890 {
00892
00893 s_t = (p0-p1)*n_proj;
00894 s_k = (pa-pb_proj)*n_01;
00895
00896
00897
00898 if(s_t==0.0)
00899 {
00900 if((p0-pa)*(n_proj)==0.0)
00901 {
00902 coord_test1 = (pa-p0)*(pa-pb_proj)/norm2_v_ab_proj;
00903 coord_test2 = (pa-p1)*(pa-pb_proj)/norm2_v_ab_proj;
00904
00905 if(coord_test1>=0)
00906 {
00907 coord_k=coord_test1;
00908 coord_t=0.0;
00909 }
00910 else
00911 {
00912 coord_k=coord_test2;
00913 coord_t=1.0;
00914 }
00915
00916 is_intersected = (coord_k > 0.0 && (coord_t >= 0.0 && coord_t <= 1.0));
00917
00918 }else
00919 {
00920 is_intersected=false;
00921 }
00922 }
00923 else
00924 {
00925 coord_k=double((pa-p0)*(n_01))*1.0/double(s_k);
00926 coord_t=double((p0-pa)*(n_proj))*1.0/double(s_t);
00927
00928 is_intersected = ((coord_k > 0.0) && (coord_t >= 0.0 && coord_t <= 1.0));
00929 }
00930
00931 if(is_intersected)
00932 {
00933 if((!is_initialized) || (coord_k > coord_kmin))
00934 {
00935 indices.clear();
00936 indices.push_back(t[0]);
00937 indices.push_back(t[1]);
00938 baryCoef=coord_t;
00939 coord_kmin=coord_k;
00940 }
00941
00942 is_initialized=true;
00943 }
00944
00945 is_validated = is_validated || is_initialized;
00946 }
00947
00948 if(!is_full_12)
00949 {
00951
00952 s_t = (p1-p2)*(n_proj);
00953 s_k = (pa-pb_proj)*(n_12);
00954
00955
00956
00957 if(s_t==0.0)
00958 {
00959 if((p1-pa)*(n_proj)==0.0)
00960 {
00961 coord_test1 = (pa-p1)*(pa-pb_proj)/norm2_v_ab_proj;
00962 coord_test2 = (pa-p2)*(pa-pb_proj)/norm2_v_ab_proj;
00963
00964 if(coord_test1>=0)
00965 {
00966 coord_k=coord_test1;
00967 coord_t=0.0;
00968 }
00969 else
00970 {
00971 coord_k=coord_test2;
00972 coord_t=1.0;
00973 }
00974
00975 is_intersected = (coord_k > 0.0 && (coord_t >= 0.0 && coord_t <= 1.0));
00976 }
00977 else
00978 {
00979 is_intersected=false;
00980 }
00981
00982 }else{
00983
00984 coord_k=double((pa-p1)*(n_12))*1.0/double(s_k);
00985 coord_t=double((p1-pa)*(n_proj))*1.0/double(s_t);
00986
00987 is_intersected = ((coord_k > 0.0) && (coord_t >= 0.0 && coord_t <= 1.0));
00988 }
00989
00990 if(is_intersected)
00991 {
00992 if((!is_initialized) || (coord_k > coord_kmin))
00993 {
00994 indices.clear();
00995 indices.push_back(t[1]);
00996 indices.push_back(t[2]);
00997 baryCoef=coord_t;
00998 coord_kmin=coord_k;
00999 }
01000
01001 is_initialized=true;
01002 }
01003
01004 is_validated = is_validated || is_initialized;
01005 }
01006
01007 if(!is_full_20)
01008 {
01010
01011 s_t = (p2-p0)*(n_proj);
01012 s_k = (pa-pb_proj)*(n_20);
01013
01014
01015
01016 if(s_t==0.0)
01017 {
01018 if((p2-pa)*(n_proj)==0.0)
01019 {
01020 coord_test1 = (pa-p2)*(pa-pb_proj)/norm2_v_ab_proj;
01021 coord_test2 = (pa-p0)*(pa-pb_proj)/norm2_v_ab_proj;
01022
01023 if(coord_test1>=0)
01024 {
01025 coord_k=coord_test1;
01026 coord_t=0.0;
01027 }
01028 else
01029 {
01030 coord_k=coord_test2;
01031 coord_t=1.0;
01032 }
01033
01034 is_intersected = (coord_k > 0.0 && (coord_t >= 0.0 && coord_t <= 1.0));
01035
01036 }
01037 else
01038 {
01039 is_intersected = false;
01040 }
01041 }
01042 else
01043 {
01044 coord_k=double((pa-p2)*(n_20))*1.0/double(s_k);
01045 coord_t=double((p2-pa)*(n_proj))*1.0/double(s_t);
01046
01047 is_intersected = ((coord_k > 0.0) && (coord_t >= 0.0 && coord_t <= 1.0));
01048 }
01049
01050 if(is_intersected)
01051 {
01052 if((!is_initialized) || (coord_k > coord_kmin))
01053 {
01054 indices.clear();
01055 indices.push_back(t[2]);
01056 indices.push_back(t[0]);
01057 baryCoef=coord_t;
01058 coord_kmin=coord_k;
01059 }
01060
01061 is_initialized = true;
01062 }
01063
01064 is_validated = is_validated || is_initialized;
01065 }
01066 }
01067 else
01068 {
01069 is_validated = false;
01070 }
01071 }
01072 else
01073 {
01074 is_validated = false;
01075 }
01076
01077 return is_validated;
01078 }
01079
01080
01081
01082
01083 template<class DataTypes>
01084 bool TriangleSetGeometryAlgorithms< DataTypes >::computeIntersectedPointsList(const Vec<3,double>& a,
01085 const Vec<3,double>& b,
01086 const unsigned int ind_ta,
01087 unsigned int& ind_tb,
01088 sofa::helper::vector< unsigned int > &triangles_list,
01089 sofa::helper::vector< sofa::helper::vector<unsigned int> > &indices_list,
01090 sofa::helper::vector< double >& coords_list, bool& is_on_boundary)
01091 {
01092 bool is_validated=true;
01093 bool is_intersected=true;
01094
01095 Vec<3,double> c_t_test = a;
01096
01097 is_on_boundary = false;
01098
01099 sofa::helper::vector<unsigned int> init_indices;
01100 sofa::helper::vector<unsigned int> &indices=init_indices;
01101
01102 double init_t=0.0;
01103 double init_k=0.0;
01104 double init_k_test=0.0;
01105
01106 double& coord_t=init_t;
01107 double& coord_k=init_k;
01108
01109 Vec<3,double> p_current=a;
01110 unsigned int ind_t_current=ind_ta;
01111
01112 unsigned int ind_edge;
01113 unsigned int ind_index;
01114 unsigned int ind_triangle = ind_ta;
01115 double coord_k_test=init_k_test;
01116
01117 const Vec<3,double>& p_const=p_current;
01118
01119 double dist_min=0.0;
01120
01121 is_intersected=computeSegmentTriangleIntersection(false, p_const, b, (const unsigned int) ind_t_current, indices, coord_t, coord_k);
01122
01123 coord_k_test=coord_k;
01124 dist_min=(b-a)*(b-a);
01125
01126 while((coord_k_test<1.0 && is_validated) && is_intersected)
01127 {
01128 ind_edge=this->m_topology->getEdgeIndex(indices[0],indices[1]);
01129 sofa::helper::vector< unsigned int > indices_first_list;
01130 indices_first_list.push_back(indices[0]);
01131 indices_first_list.push_back(indices[1]);
01132 triangles_list.push_back(ind_t_current);
01133 indices_list.push_back(indices_first_list);
01134 coords_list.push_back(coord_t);
01135
01136 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
01137
01138 Vec<3,double> c_t_current;
01139 c_t_current[0]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][0]))+coord_t*((double) (vect_c[indices[1]][0])));
01140 c_t_current[1]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][1]))+coord_t*((double) (vect_c[indices[1]][1])));
01141 c_t_current[2]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][2]))+coord_t*((double) (vect_c[indices[1]][2])));
01142
01143 p_current=c_t_current;
01144
01145 Vec<3,Real> p_t_aux;
01146 p_t_aux[0] = (Real) (c_t_current[0]);
01147 p_t_aux[1] = (Real) (c_t_current[1]);
01148 p_t_aux[2] = (Real) (c_t_current[2]);
01149
01150 if(coord_t==0.0 || coord_t==1.0)
01151 {
01152
01153
01154 if(coord_t==0.0)
01155 {
01156 ind_index=indices[0];
01157 }
01158 else
01159 {
01160 ind_index=indices[1];
01161 }
01162
01163 if (this->m_topology->getNbPoints() >0)
01164 {
01165 sofa::helper::vector< unsigned int > shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleVertexShell(ind_index));
01166 ind_triangle=shell[0];
01167 unsigned int i=0;
01168
01169 bool is_test_init=false;
01170
01171 unsigned int ind_from = ind_t_current;
01172
01173 if(shell.size()>1)
01174 {
01175 is_on_boundary=false;
01176
01177 while(i < shell.size())
01178 {
01179 if(shell[i] != ind_from)
01180 {
01181 ind_triangle=shell[i];
01182
01183 const Triangle &t=this->m_topology->getTriangle(ind_triangle);
01184
01185 const typename DataTypes::Coord& c0=vect_c[t[0]];
01186 const typename DataTypes::Coord& c1=vect_c[t[1]];
01187 const typename DataTypes::Coord& c2=vect_c[t[2]];
01188
01189 Vec<3,Real> p0_aux;
01190 p0_aux[0] = (Real) (c0[0]);
01191 p0_aux[1] = (Real) (c0[1]);
01192 p0_aux[2] = (Real) (c0[2]);
01193 Vec<3,Real> p1_aux;
01194 p1_aux[0] = (Real) (c1[0]);
01195 p1_aux[1] = (Real) (c1[1]);
01196 p1_aux[2] = (Real) (c1[2]);
01197 Vec<3,Real> p2_aux;
01198 p2_aux[0] = (Real) (c2[0]);
01199 p2_aux[1] = (Real) (c2[1]);
01200 p2_aux[2] = (Real) (c2[2]);
01201
01202 const Vec<3,double>& p_const_current=p_current;
01203 is_intersected=computeSegmentTriangleIntersection(true, p_const_current, b, ind_triangle, indices, coord_t, coord_k);
01204
01205 if(is_intersected)
01206 {
01207 Vec<3,double> c_t_test;
01208 c_t_test[0]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][0]))+coord_t*((double) (vect_c[indices[1]][0])));
01209 c_t_test[1]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][1]))+coord_t*((double) (vect_c[indices[1]][1])));
01210 c_t_test[2]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][2]))+coord_t*((double) (vect_c[indices[1]][2])));
01211
01212 double dist_test=(b-c_t_test)*(b-c_t_test);
01213
01214 if(is_test_init)
01215 {
01216 if(dist_test<dist_min && coord_k<=1)
01217 {
01218 coord_k_test=coord_k;
01219 dist_min=dist_test;
01220 ind_t_current=ind_triangle;
01221 }
01222 }
01223 else
01224 {
01225 is_test_init=true;
01226 coord_k_test=coord_k;
01227 dist_min=dist_test;
01228 ind_t_current=ind_triangle;
01229 }
01230 }
01231 }
01232
01233 i=i+1;
01234 }
01235
01236 is_intersected=is_test_init;
01237
01238 }
01239 else
01240 {
01241 is_on_boundary=true;
01242 is_validated=false;
01243 }
01244 }
01245 else
01246 {
01247 is_validated=false;
01248 }
01249 }
01250 else
01251 {
01252 ind_edge=this->m_topology->getEdgeIndex(indices[0],indices[1]);
01253
01254 if (this->m_topology->getNbEdges()>0)
01255 {
01256 sofa::helper::vector< unsigned int > shell =(sofa::helper::vector< unsigned int >) (this->m_topology->getTriangleEdgeShell(ind_edge));
01257 ind_triangle=shell[0];
01258 unsigned int i=0;
01259
01260 bool is_test_init=false;
01261
01262 unsigned int ind_from = ind_t_current;
01263
01264 if(shell.size()>1)
01265 {
01266 is_on_boundary=false;
01267
01268 while(i < shell.size())
01269 {
01270 if(shell[i] != ind_from)
01271 {
01272 ind_triangle=shell[i];
01273
01274 const Triangle &t=this->m_topology->getTriangle(ind_triangle);
01275
01276 const typename DataTypes::Coord& c0=vect_c[t[0]];
01277 const typename DataTypes::Coord& c1=vect_c[t[1]];
01278 const typename DataTypes::Coord& c2=vect_c[t[2]];
01279
01280 Vec<3,Real> p0_aux;
01281 p0_aux[0] = (Real) (c0[0]);
01282 p0_aux[1] = (Real) (c0[1]);
01283 p0_aux[2] = (Real) (c0[2]);
01284 Vec<3,Real> p1_aux;
01285 p1_aux[0] = (Real) (c1[0]);
01286 p1_aux[1] = (Real) (c1[1]);
01287 p1_aux[2] = (Real) (c1[2]);
01288 Vec<3,Real> p2_aux;
01289 p2_aux[0] = (Real) (c2[0]);
01290 p2_aux[1] = (Real) (c2[1]);
01291 p2_aux[2] = (Real) (c2[2]);
01292
01293 const Vec<3,double>& p_const_current=p_current;
01294 is_intersected=computeSegmentTriangleIntersection(true, p_const_current, b, ind_triangle, indices, coord_t, coord_k);
01295
01296 if(is_intersected)
01297 {
01298
01299 c_t_test[0]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][0]))+coord_t*((double) (vect_c[indices[1]][0])));
01300 c_t_test[1]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][1]))+coord_t*((double) (vect_c[indices[1]][1])));
01301 c_t_test[2]=(double) ((1.0-coord_t)*((double) (vect_c[indices[0]][2]))+coord_t*((double) (vect_c[indices[1]][2])));
01302
01303 double dist_test=(b-c_t_test)*(b-c_t_test);
01304
01305 if(is_test_init)
01306 {
01307 if(dist_test<dist_min && coord_k<=1)
01308 {
01309 coord_k_test=coord_k;
01310 dist_min=dist_test;
01311 ind_t_current=ind_triangle;
01312 }
01313 }
01314 else
01315 {
01316 is_test_init=true;
01317 coord_k_test=coord_k;
01318 dist_min=dist_test;
01319 ind_t_current=ind_triangle;
01320 }
01321 }
01322 }
01323
01324 i=i+1;
01325 }
01326
01327 is_intersected=is_test_init;
01328 }
01329 else
01330 {
01331 is_on_boundary=true;
01332 is_validated=false;
01333 }
01334 }
01335 else
01336 {
01337 is_validated=false;
01338 }
01339 }
01340 }
01341
01342 bool is_reached = (ind_tb==ind_triangle && coord_k_test>=1.0);
01343
01344 if(is_reached)
01345 {
01346 std::cout << "INFO_print - TriangleSetTopology.inl : Cut is reached" << std::endl;
01347 }
01348
01349 if(is_on_boundary)
01350 {
01351 std::cout << "INFO_print - TriangleSetTopology.inl : Cut meets a mesh boundary" << std::endl;
01352 }
01353
01354 if(!is_reached && !is_on_boundary)
01355 {
01356 std::cout << "INFO_print - TriangleSetTopology.inl : Cut is not reached" << std::endl;
01357 ind_tb=ind_triangle;
01358 }
01359
01360 return (is_reached && is_validated && is_intersected);
01361 }
01362
01364 template <typename DataTypes>
01365 void TriangleSetGeometryAlgorithms<DataTypes>::writeMSHfile(const char *filename)
01366 {
01367 std::ofstream myfile;
01368 myfile.open (filename);
01369
01370 const typename DataTypes::VecCoord& vect_c = *(this->object->getX());
01371
01372 const unsigned int numVertices = vect_c.size();
01373
01374 myfile << "$NOD\n";
01375 myfile << numVertices <<"\n";
01376
01377 for (unsigned int i=0; i<numVertices; ++i)
01378 {
01379 double x = (double) vect_c[i][0];
01380 double y = (double) vect_c[i][1];
01381 double z = (double) vect_c[i][2];
01382
01383 myfile << i+1 << " " << x << " " << y << " " << z <<"\n";
01384 }
01385
01386 myfile << "$ENDNOD\n";
01387 myfile << "$ELM\n";
01388
01389 const sofa::helper::vector<Triangle> &ta=this->m_topology->getTriangles();
01390
01391 myfile << ta.size() <<"\n";
01392
01393 for (unsigned int i=0; i<ta.size(); ++i)
01394 {
01395 myfile << i+1 << " 2 6 6 3 " << ta[i][0]+1 << " " << ta[i][1]+1 << " " << ta[i][2]+1 <<"\n";
01396 }
01397
01398 myfile << "$ENDELM\n";
01399
01400 myfile.close();
01401 }
01402
01404
01405 template<class Real>
01406 bool is_point_in_triangle(const Vec<3,Real>& p, const Vec<3,Real>& a, const Vec<3,Real>& b, const Vec<3,Real>& c)
01407 {
01408 Vec<3,Real> ptest = p;
01409
01410 Vec<3,Real> p0 = a;
01411 Vec<3,Real> p1 = b;
01412 Vec<3,Real> p2 = c;
01413
01414 Vec<3,Real> v_normal = (p2-p0).cross(p1-p0);
01415
01416 Real norm_v_normal = v_normal*(v_normal);
01417 if(norm_v_normal != 0.0)
01418 {
01419
01420
01421 if((ptest-p0)*(v_normal)==0.0)
01422 {
01423
01424 Vec<3,Real> n_01 = (p1-p0).cross(v_normal);
01425 Vec<3,Real> n_12 = (p2-p1).cross(v_normal);
01426 Vec<3,Real> n_20 = (p0-p2).cross(v_normal);
01427
01428 return (((ptest-p0)*(n_01) >= 0.0) && ((ptest-p1)*(n_12) >= 0.0) && ((ptest-p2)*(n_20) >= 0.0));
01429
01430 }
01431 else
01432 {
01433
01434 return false;
01435 }
01436
01437 }
01438 else
01439 {
01440
01441 return false;
01442 }
01443 }
01444
01446
01447 template<class Real>
01448 bool is_point_in_halfplane(const Vec<3,Real>& p, unsigned int e0, unsigned int e1,
01449 const Vec<3,Real>& a, const Vec<3,Real>& b, const Vec<3,Real>& c,
01450 unsigned int ind_p0, unsigned int ind_p1, unsigned int ind_p2)
01451 {
01452 Vec<3,Real> ptest = p;
01453
01454 Vec<3,Real> p0 = a;
01455 Vec<3,Real> p1 = b;
01456 Vec<3,Real> p2 = c;
01457
01458 Vec<3,Real> v_normal = (p2-p0).cross(p1-p0);
01459
01460 Real norm_v_normal = (v_normal)*(v_normal);
01461
01462 if(norm_v_normal != 0.0)
01463 {
01464
01465
01466 if(ind_p0==e0 || ind_p0==e1)
01467 {
01468 Vec<3,Real> n_12 = (p2-p1).cross(v_normal);
01469 return ((ptest-p1)*(n_12) >= 0.0);
01470 }
01471 else
01472 {
01473 if(ind_p1==e0 || ind_p1==e1)
01474 {
01475 Vec<3,Real> n_20 = (p0-p2).cross(v_normal);
01476 return ((ptest-p2)*(n_20) >= 0.0);
01477 }
01478 else
01479 {
01480 if(ind_p2==e0 || ind_p2==e1)
01481 {
01482 Vec<3,Real> n_01 = (p1-p0).cross(v_normal);
01483 return ((ptest-p0)*(n_01) >= 0.0);
01484 }
01485 else
01486 {
01487 return false;
01488 }
01489 }
01490 }
01491 }
01492 else
01493 {
01494
01495 return false;
01496 }
01497 }
01498
01500 template< class Real>
01501 Real areaProduct(const Vec<3,Real>& a, const Vec<3,Real>& b)
01502 {
01503 return Vec<3,Real>(a.y()*b.z() - a.z()*b.y(),
01504 a.z()*b.x() - a.x()*b.z(),
01505 a.x()*b.y() - a.y()*b.x()).norm();
01506 }
01507
01509 template< class Real>
01510 Real areaProduct(const defaulttype::Vec<2,Real>& a, const defaulttype::Vec<2,Real>& b )
01511 {
01512 return a[0]*b[1] - a[1]*b[0];
01513 }
01514
01516 template< class Real>
01517 Real areaProduct(const defaulttype::Vec<1,Real>& , const defaulttype::Vec<1,Real>& )
01518 {
01519 assert(false);
01520 return (Real)0;
01521 }
01522
01523 }
01524
01525 }
01526
01527 }
01528
01529 #endif // SOFA_COMPONENTS_TriangleSetTOPOLOGY_INL