TriangleSetGeometryAlgorithms.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_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     // Computes the point defined by 2 indices of vertex and 1 barycentric coordinate
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     // Computes the opposite point to ind_p
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     // Computes the normal vector of a triangle indexed by ind_t (not normed)
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     // barycentric coefficients of point p in triangle (a,b,c) indexed by ind_t
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) // triangle (a,b,c) is flat
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)); //N*((a-p).cross(b-p));
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     // barycentric coefficients of point p in triangle whose vertices are indexed by (ind_p1,ind_p2,ind_p3)
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) // triangle (a,b,c) is flat
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)); //N*((a-p).cross(b-p));
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     // Find the two closest points from two triangles (each of the point belonging to one triangle)
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     // test if a point is included in the triangle indexed by ind_t
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 // v_01 < 0.0
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 // v_12 < 0.0
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 // v_20 < 0.0
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                         //std::cout << "correct to triangle indexed by " << ind_t_test << std::endl;
00432                     }
00433                     else // not found
00434                     {
00435                         //std::cout << "not found !!! " << std::endl;
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 // triangle is flat
00448         {
00449             //std::cout << "INFO_print : triangle is flat" << std::endl;
00450             return false;
00451         }
00452     }
00453 
00454     // Tests how to triangularize a quad whose vertices are defined by (p_q1, p_q2, ind_q3, ind_q4) according to the Delaunay criterion
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     // Test if a triangle indexed by ind_triangle (and incident to the vertex indexed by ind_p) is included or not in the plane defined by (ind_p, plane_vect)
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         // HYP : ind_p==t[0] or ind_p==t[1] or ind_p==t[2] 
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 // ind_p==t[2]
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     // Prepares the duplication of a vertex
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         //HYP : if coord_from or coord_to == 0.0 or 1.0, ind_p is distinct from ind_from and from ind_to                    
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         //Vec<3,Real> point_from=(Vec<3,Real>) computeBaryEdgePoint((sofa::helper::vector< unsigned int>&) indices_from, coord_from);
00570         //Vec<3,Real> point_to=(Vec<3,Real>) computeBaryEdgePoint((sofa::helper::vector< unsigned int>&) indices_to, coord_to);
00571 
00572         Vec<3,Real> vect_from = point_from - point_p;
00573         Vec<3,Real> vect_to = point_p - point_to;
00574 
00575         //std::cout << "INFO_print : vect_from = " << vect_from <<  std::endl;
00576         //std::cout << "INFO_print : vect_to = " << vect_to <<  std::endl;
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); // inverse ??
00588         }
00589         else
00590         {
00591             // HYP : only 2 edges maximum are adjacent to the same triangle (otherwise : compute the one which minimizes the normed dotProduct and which gives the positive cross)
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 // coord_from==1.0
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             // HYP : only 2 edges maximum are adjacent to the same triangle (otherwise : compute the one which minimizes the normed dotProduct and which gives the positive cross)
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 // coord_to==1.0
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                     //std::cout << "INFO_print : CONVEXE, value_test = " << value_test <<  std::endl;
00720                     //std::cout << "INFO_print : shell.size() = " << shell.size() << ", ind_t_from = " << ind_t_from << ", ind_t_to = " << ind_t_to <<  std::endl;
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 // value_test>0.0
00744                 {
00745                     //std::cout << "INFO_print : CONCAVE, value_test = " << value_test <<  std::endl;
00746                     //std::cout << "INFO_print : shell.size() = " << shell.size() << ", ind_t_from = " << ind_t_from << ", ind_t_to = " << ind_t_to <<  std::endl;
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     // Computes the intersection of the segment from point a to point b and the triangle indexed by t
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         // HYP : point a is in triangle indexed by t
00798         // is_entered == true => indices.size() == 2
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         //Vec<3,Real> v_normal = (Vec<3,Real>) computeTriangleNormal(ind_t);
00849 
00850         Real norm_v_normal = v_normal.norm(); // WARN : square root COST
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); // projection
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) // pb_proj != pa
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                     // s_t == 0.0 iff s_k == 0.0
00897 
00898                     if(s_t==0.0) // (pa,pb_proj) and (p0,p1) are parallel
00899                     {
00900                         if((p0-pa)*(n_proj)==0.0) // (pa,pb_proj) and (p0,p1) are on the same line
00901                         {
00902                             coord_test1 = (pa-p0)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
00903                             coord_test2 = (pa-p1)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
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 // (pa,pb_proj) and (p0,p1) are parallel and disjoint
00919                         {
00920                             is_intersected=false;
00921                         }
00922                     }
00923                     else // s_t != 0.0 and s_k != 0.0
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                     // s_t == 0.0 iff s_k == 0.0
00956 
00957                     if(s_t==0.0) // (pa,pb_proj) and (p1,p2) are parallel
00958                     {
00959                         if((p1-pa)*(n_proj)==0.0) // (pa,pb_proj) and (p1,p2) are on the same line
00960                         {
00961                             coord_test1 = (pa-p1)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
00962                             coord_test2 = (pa-p2)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
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 // (pa,pb_proj) and (p1,p2) are parallel and disjoint
00978                         {
00979                             is_intersected=false;
00980                         }
00981 
00982                     }else{ // s_t != 0.0 and s_k != 0.0
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                     // s_t == 0.0 iff s_k == 0.0
01015 
01016                     if(s_t==0.0) // (pa,pb_proj) and (p2,p0) are parallel
01017                     {
01018                         if((p2-pa)*(n_proj)==0.0) // (pa,pb_proj) and (p2,p0) are on the same line
01019                         {
01020                             coord_test1 = (pa-p2)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
01021                             coord_test2 = (pa-p0)*(pa-pb_proj)/norm2_v_ab_proj; // HYP : pb_proj != pa
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 // (pa,pb_proj) and (p2,p0) are parallel and disjoint
01038                         {
01039                             is_intersected = false;
01040                         }
01041                     }
01042                     else // s_t != 0.0 and s_k != 0.0
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; // points a and b are projected to the same point on triangle t
01070             }
01071         }
01072         else
01073         {
01074             is_validated = false; // triangle t is flat
01075         }
01076 
01077         return is_validated;    
01078     }
01079 
01080 
01081     // Computes the list of points (edge,coord) intersected by the segment from point a to point b 
01082     // and the triangular mesh
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; // WARNING : conversion from 'double' to 'float', possible loss of data ! // typename DataTypes::Coord
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) // current point indexed by ind_t_current is on a vertex
01151             {
01152                 //std::cout << "INFO_print : INPUT ON A VERTEX !!!" <<  std::endl;
01153 
01154                 if(coord_t==0.0)
01155                 {
01156                     ind_index=indices[0];
01157                 }
01158                 else // coord_t==1.0
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                     //bool is_in_next_triangle=false;
01169                     bool is_test_init=false;
01170 
01171                     unsigned int ind_from = ind_t_current;
01172 
01173                     if(shell.size()>1) // at leat one neighbor triangle which is not indexed by ind_t_current
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; // WARNING : conversion from 'double' to 'float', possible loss of data ! // typename DataTypes::Coord
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) //dist_test<dist_min
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 // current point indexed by ind_t_current is on an edge, but not on a vertex
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) // at leat one neighbor triangle which is not indexed by ind_t_current
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                                     //Vec<3,double> c_t_test; // WARNING : conversion from 'double' to 'float', possible loss of data ! // typename DataTypes::Coord
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) //dist_test<dist_min
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); // b is in triangle indexed by ind_t_current
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             //v_normal/=norm_v_normal; 
01420 
01421             if((ptest-p0)*(v_normal)==0.0) // p is in the plane defined by the triangle (p0,p1,p2)
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 // p is not in the plane defined by the triangle (p0,p1,p2)
01432             {
01433                 //std::cout << "INFO_print : p is not in the plane defined by the triangle (p0,p1,p2)" << std::endl;
01434                 return false;
01435             }
01436 
01437         }
01438         else // triangle is flat
01439         {
01440             //std::cout << "INFO_print : triangle is flat" << std::endl;
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             //v_normal/=norm_v_normal; 
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; // not expected
01488                     }
01489                 }
01490             }
01491         }
01492         else // triangle is flat
01493         {
01494             //std::cout << "INFO_print : triangle is flat" << std::endl;
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 } // namespace topology
01524 
01525 } // namespace component
01526 
01527 } // namespace sofa
01528 
01529 #endif // SOFA_COMPONENTS_TriangleSetTOPOLOGY_INL

Generated on Sun Nov 23 03:47:09 2008 for Sofa by  doxygen 1.5.7.1