TriangleSetTopologyContainer.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/topology/TriangleSetTopologyContainer.h>
00026 
00027 #include <sofa/core/ObjectFactory.h>
00028 
00029 #include <sofa/component/MeshLoader.h>
00030 
00031 namespace sofa
00032 {
00033 
00034 namespace component
00035 {
00036 
00037 namespace topology
00038 {
00039     using namespace std;
00040     using namespace sofa::defaulttype;
00041 
00042 
00043   SOFA_DECL_CLASS(TriangleSetTopologyContainer)
00044   int TriangleSetTopologyContainerClass = core::RegisterObject("Triangle set topology container")
00045     .add< TriangleSetTopologyContainer >()
00046     ;
00047 
00048     TriangleSetTopologyContainer::TriangleSetTopologyContainer()
00049     : EdgeSetTopologyContainer()
00050     {}
00051 
00052 TriangleSetTopologyContainer::TriangleSetTopologyContainer(const sofa::helper::vector< Triangle > &triangles )
00053 : EdgeSetTopologyContainer()
00054 , m_triangle( triangles )
00055 {
00056     for (unsigned int i=0; i<m_triangle.size(); ++i)
00057     {
00058         for(unsigned int j=0; j<3; ++j)
00059         {
00060             int a = m_triangle[i][j];
00061             if (a >= (int)nbPoints) 
00062                 nbPoints = a+1;
00063         }
00064     }
00065 }
00066 
00067     void TriangleSetTopologyContainer::init()
00068     {
00069         EdgeSetTopologyContainer::init();
00070     }
00071 
00072     void TriangleSetTopologyContainer::loadFromMeshLoader(sofa::component::MeshLoader* loader)
00073     {
00074         // load points
00075         PointSetTopologyContainer::loadFromMeshLoader(loader);
00076         m_triangle = loader->getTriangles();
00077     }
00078 
00079 void TriangleSetTopologyContainer::addTriangle( int a, int b, int c )
00080 {
00081     m_triangle.push_back(Triangle(a,b,c));
00082     if (a >= (int)nbPoints) nbPoints = a+1;
00083     if (b >= (int)nbPoints) nbPoints = b+1;
00084     if (c >= (int)nbPoints) nbPoints = c+1;
00085 }
00086 
00087     void TriangleSetTopologyContainer::createTriangleSetArray()
00088     {
00089     #ifndef NDEBUG
00090         cout << "Error. [TriangleSetTopologyContainer::createTriangleSetArray] This method must be implemented by a child topology." << endl;
00091     #endif
00092     }
00093 
00094     void TriangleSetTopologyContainer::createTriangleVertexShellArray ()
00095     {
00096         if(!hasTriangles()) // this method should only be called when triangles exist
00097         {
00098     #ifndef NDEBUG
00099             cout << "Warning. [TriangleSetTopologyContainer::createTriangleVertexShellArray] triangle array is empty." << endl;
00100     #endif
00101             createTriangleSetArray();
00102         }
00103 
00104         if(hasTriangleVertexShell())
00105         {
00106             clearTriangleVertexShell();
00107         }
00108 
00109         m_triangleVertexShell.resize( getNbPoints() );
00110 
00111         for (unsigned int i = 0; i < m_triangle.size(); ++i)
00112         {
00113             // adding edge i in the edge shell of both points
00114             for (unsigned int j=0; j<3; ++j) 
00115                 m_triangleVertexShell[ m_triangle[i][j]  ].push_back( i );
00116         }
00117     }
00118 
00119     void TriangleSetTopologyContainer::createTriangleEdgeShellArray ()
00120     {
00121         if(!hasTriangles()) // this method should only be called when triangles exist
00122         {
00123     #ifndef NDEBUG
00124             cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeShellArray] triangle array is empty." << endl;
00125     #endif
00126             createTriangleSetArray();
00127         }
00128 
00129         if(!hasEdges()) // this method should only be called when edges exist
00130         {
00131     #ifndef NDEBUG
00132             cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeShellArray] edge array is empty." << endl;
00133     #endif
00134             createEdgeSetArray();
00135         }
00136 
00137         if(!hasTriangleEdges())
00138             createTriangleEdgeArray();
00139 
00140         const unsigned int numTriangles = getNumberOfTriangles();
00141         const unsigned int numEdges = getNumberOfEdges();
00142 
00143         if(hasTriangleEdgeShell())
00144         {
00145             clearTriangleEdgeShell();
00146         }
00147 
00148         m_triangleEdgeShell.resize( numEdges );
00149 
00150         for (unsigned int i = 0; i < numTriangles; ++i)
00151         {
00152             // adding triangle i in the triangle shell of all edges
00153             for (unsigned int j=0; j<3; ++j) 
00154             { 
00155                 m_triangleEdgeShell[ m_triangleEdge[i][j] ].push_back( i );
00156             }
00157         }
00158     }
00159 
00160     void TriangleSetTopologyContainer::createEdgeSetArray()
00161     {
00162         if(!hasTriangles()) // this method should only be called when triangles exist
00163         {
00164     #ifndef NDEBUG
00165             cout << "Warning. [TriangleSetTopologyContainer::createEdgeSetArray] triangle array is empty." << endl;
00166     #endif
00167             createTriangleSetArray();
00168         }
00169 
00170         if(hasEdges()) 
00171         {
00172         #ifndef NDEBUG
00173                 cout << "Warning. [TriangleSetTopologyContainer::createEdgeSetArray] edge array is not empty." << endl;
00174         #endif
00175 
00176             // clear edges and all shells that depend on edges
00177             EdgeSetTopologyContainer::clear();
00178 
00179             if(hasTriangleEdges())
00180                 clearTriangleEdges();
00181 
00182             if(hasTriangleEdgeShell())
00183                 clearTriangleEdgeShell();
00184         }
00185 
00186         // create a temporary map to find redundant edges
00187         std::map<Edge, unsigned int> edgeMap;
00188 
00189         for (unsigned int i=0; i<m_triangle.size(); ++i)
00190         {
00191             const Triangle &t = m_triangle[i];
00192             for(unsigned int j=0; j<3; ++j)
00193             { 
00194                 const unsigned int v1 = t[(j+1)%3];
00195                 const unsigned int v2 = t[(j+2)%3];
00196 
00197                 // sort vertices in lexicographic order
00198                 const Edge e = ((v1<v2) ? Edge(v1,v2) : Edge(v2,v1));
00199 
00200                 if(edgeMap.find(e) == edgeMap.end()) 
00201                 {
00202                 // edge not in edgeMap so create a new one
00203                     const int edgeIndex = edgeMap.size();
00204                     edgeMap[e] = edgeIndex;
00205                     m_edge.push_back(e);
00206                 } 
00207             }
00208         }
00209     }
00210 
00211     void TriangleSetTopologyContainer::createTriangleEdgeArray()
00212     {
00213         if(!hasTriangles()) // this method should only be called when triangles exist
00214         {
00215     #ifndef NDEBUG
00216             cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeArray] triangle array is empty." << endl;
00217     #endif
00218             createTriangleSetArray();
00219         }
00220 
00221         if(!hasEdges()) // this method should only be called when edges exist
00222         {
00223     #ifndef NDEBUG
00224             cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeArray] edge array is empty." << endl;
00225     #endif
00226             createEdgeSetArray();
00227         }
00228 
00229         if(hasTriangleEdges())
00230             clearTriangleEdges();
00231 
00232         const unsigned int numTriangles = getNumberOfTriangles();
00233 
00234         m_triangleEdge.resize(numTriangles);
00235         for(unsigned int i=0; i<numTriangles; ++i)
00236         {
00237             Triangle &t = m_triangle[i];
00238             // adding edge i in the edge shell of both points
00239             for(unsigned int j=0; j<3; ++j) 
00240             { 
00241                 int edgeIndex = getEdgeIndex(t[(j+1)%3],t[(j+2)%3]);
00242                 m_triangleEdge[i][j] = edgeIndex; 
00243             }
00244         }
00245     }
00246 
00247     const sofa::helper::vector<Triangle> & TriangleSetTopologyContainer::getTriangleArray()
00248     {
00249         if(!hasTriangles() && getNbPoints()>0) 
00250         {
00251     #ifndef NDEBUG
00252             cout << "[TriangleSetTopologyContainer::getTriangleArray] creating triangle array." << endl;
00253     #endif
00254             createTriangleSetArray();
00255         }
00256 
00257         return m_triangle;
00258     }
00259 
00260 
00261     int TriangleSetTopologyContainer::getTriangleIndex(PointID v1, PointID v2, PointID v3)
00262     {
00263         if(!hasTriangleVertexShell())
00264             createTriangleVertexShellArray();
00265 
00266         sofa::helper::vector<unsigned int> set1 = getTriangleVertexShell(v1);
00267         sofa::helper::vector<unsigned int> set2 = getTriangleVertexShell(v2);
00268         sofa::helper::vector<unsigned int> set3 = getTriangleVertexShell(v3);
00269 
00270         sort(set1.begin(), set1.end());
00271         sort(set2.begin(), set2.end());
00272         sort(set3.begin(), set3.end());
00273 
00274         // The destination vector must be large enough to contain the result.
00275         sofa::helper::vector<unsigned int> out1(set1.size()+set2.size());
00276         sofa::helper::vector<unsigned int>::iterator result1;
00277         result1 = std::set_intersection(set1.begin(),set1.end(),set2.begin(),set2.end(),out1.begin());
00278         out1.erase(result1,out1.end());
00279 
00280         sofa::helper::vector<unsigned int> out2(set3.size()+out1.size());
00281         sofa::helper::vector<unsigned int>::iterator result2;
00282         result2 = std::set_intersection(set3.begin(),set3.end(),out1.begin(),out1.end(),out2.begin());
00283         out2.erase(result2,out2.end());
00284 
00285     #ifndef NDEBUG
00286         if(out2.size() > 1)
00287             cout << "Warning. [TriangleSetTopologyContainer::getTriangleIndex] more than one triangle found" << endl;
00288     #endif
00289 
00290         if (out2.size()==1)
00291             return (int) (out2[0]);
00292         else
00293             return -1;
00294     }
00295 
00296     unsigned int TriangleSetTopologyContainer::getNumberOfTriangles() const
00297     {
00298         return m_triangle.size();
00299     }
00300 
00301     const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TriangleSetTopologyContainer::getTriangleVertexShellArray() 
00302     {
00303         if(!hasTriangleVertexShell())   // this method should only be called when the shell array exists
00304         {
00305     #ifndef NDEBUG
00306             cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShellArray] triangle vertex shell array is empty." << endl;
00307     #endif
00308             createTriangleVertexShellArray();
00309         }
00310 
00311         return m_triangleVertexShell;
00312     }
00313 
00314     const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TriangleSetTopologyContainer::getTriangleEdgeShellArray() 
00315     {
00316         if(!hasTriangleEdgeShell()) // this method should only be called when the shell array exists
00317         {
00318     #ifndef NDEBUG
00319             cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShellArray] triangle edge shell array is empty." << endl;
00320     #endif
00321             createTriangleEdgeShellArray();
00322         }
00323 
00324         return m_triangleEdgeShell;
00325     }
00326 
00327     const sofa::helper::vector<TriangleEdges> &TriangleSetTopologyContainer::getTriangleEdgeArray() 
00328     {
00329         if(m_triangleEdge.empty())
00330             createTriangleEdgeArray();
00331 
00332         return m_triangleEdge;
00333     }
00334 
00335     const VertexTriangles& TriangleSetTopologyContainer::getTriangleVertexShell(PointID i)
00336     {
00337         if(!hasTriangleVertexShell())   // this method should only be called when the shell array exists
00338         {
00339     #ifndef NDEBUG
00340             cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShell] triangle vertex shell array is empty." << endl;
00341     #endif
00342             createTriangleVertexShellArray();
00343         }
00344         else if( i >= m_triangleVertexShell.size())
00345         {
00346     #ifndef NDEBUG
00347             cout << "Error. [TriangleSetTopologyContainer::getTriangleVertexShell] index out of bounds." << endl;
00348     #endif
00349             createTriangleVertexShellArray();
00350         }
00351 
00352         return m_triangleVertexShell[i];
00353     }
00354 
00355     const EdgeTriangles& TriangleSetTopologyContainer::getTriangleEdgeShell(EdgeID i)
00356     {
00357         if(!hasTriangleEdgeShell()) // this method should only be called when the shell array exists
00358         {
00359     #ifndef NDEBUG
00360             cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShell] triangle edge shell array is empty." << endl;
00361     #endif
00362             createTriangleEdgeShellArray();
00363         }
00364         else if( i >= m_triangleEdgeShell.size())
00365         {
00366     #ifndef NDEBUG
00367             cout << "Error. [TriangleSetTopologyContainer::getTriangleEdgeShell] index out of bounds." << endl;
00368     #endif
00369             createTriangleEdgeShellArray();
00370         }
00371 
00372         return m_triangleEdgeShell[i];
00373     }
00374 
00375     const TriangleEdges &TriangleSetTopologyContainer::getTriangleEdge(const unsigned int i) 
00376     {
00377         if(m_triangleEdge.empty())
00378             createTriangleEdgeArray();
00379         
00380         if( i >= m_triangleEdge.size())
00381         {
00382     #ifndef NDEBUG
00383             cout << "Error. [TriangleSetTopologyContainer::getTriangleEdge] index out of bounds." << endl;
00384     #endif
00385             createTriangleEdgeArray();
00386         }
00387 
00388         return m_triangleEdge[i];
00389     }
00390 
00391     int TriangleSetTopologyContainer::getVertexIndexInTriangle(const Triangle &t, PointID vertexIndex) const
00392     {
00393         if (t[0]==vertexIndex)
00394             return 0;
00395         else if (t[1]==vertexIndex)
00396             return 1;
00397         else if (t[2]==vertexIndex)
00398             return 2;
00399         else 
00400             return -1;
00401     }
00402 
00403     int TriangleSetTopologyContainer::getEdgeIndexInTriangle(const TriangleEdges &t, EdgeID edgeIndex) const
00404     {
00405         if (t[0]==edgeIndex)
00406             return 0;
00407         else if (t[1]==edgeIndex)
00408             return 1;
00409         else if (t[2]==edgeIndex)
00410             return 2;
00411         else 
00412             return -1;
00413     }
00414 
00415     sofa::helper::vector< unsigned int > &TriangleSetTopologyContainer::getTriangleEdgeShellForModification(const unsigned int i) 
00416     {
00417         if(!hasTriangleEdgeShell()) // this method should only be called when the shell array exists
00418         {
00419     #ifndef NDEBUG
00420             cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShellForModification] triangle edge shell array is empty." << endl;
00421     #endif
00422             createTriangleEdgeShellArray();
00423         }
00424         
00425         if( i >= m_triangleEdgeShell.size())
00426         {
00427     #ifndef NDEBUG
00428             cout << "Error. [TriangleSetTopologyContainer::getTriangleEdgeShellForModification] index out of bounds." << endl;
00429     #endif
00430             createTriangleEdgeShellArray();
00431         }
00432 
00433         return m_triangleEdgeShell[i];
00434     }
00435 
00436     sofa::helper::vector< unsigned int > &TriangleSetTopologyContainer::getTriangleVertexShellForModification(const unsigned int i) 
00437     {
00438         if(!hasTriangleVertexShell())   // this method should only be called when the shell array exists
00439         {
00440     #ifndef NDEBUG
00441             cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShellForModification] triangle vertex shell array is empty." << endl;
00442     #endif
00443             createTriangleVertexShellArray();
00444         }
00445         
00446         if( i >= m_triangleVertexShell.size())
00447         {
00448     #ifndef NDEBUG
00449             cout << "Error. [TriangleSetTopologyContainer::getTriangleVertexShellForModification] index out of bounds." << endl;
00450     #endif
00451             createTriangleVertexShellArray();
00452         }
00453 
00454         return m_triangleVertexShell[i];
00455     }
00456 
00457     bool TriangleSetTopologyContainer::checkTopology() const
00458     {
00459     #ifndef NDEBUG
00460         bool ret = true;
00461 
00462         if (hasTriangleVertexShell()) 
00463         {
00464             for (unsigned int i=0; i<m_triangleVertexShell.size(); ++i) 
00465             {
00466                 const sofa::helper::vector<unsigned int> &tvs = m_triangleVertexShell[i];
00467                 for (unsigned int j=0; j<tvs.size(); ++j)
00468                 {
00469                     bool check_triangle_vertex_shell = (m_triangle[tvs[j]][0]==i) 
00470                                                     || (m_triangle[tvs[j]][1]==i) 
00471                                                     || (m_triangle[tvs[j]][2]==i);
00472                     if(!check_triangle_vertex_shell)
00473                     {
00474                         std::cout << "*** CHECK FAILED : check_triangle_vertex_shell, i = " << i << " , j = " << j << std::endl;
00475                         ret = false;
00476                     }
00477                 }
00478             }
00479         }
00480 
00481         if (hasTriangleEdgeShell()) 
00482         {
00483             for (unsigned int i=0;i<m_triangleEdgeShell.size();++i) 
00484             {
00485                 const sofa::helper::vector<unsigned int> &tes=m_triangleEdgeShell[i];
00486                 for (unsigned int j=0;j<tes.size();++j)
00487                 {
00488                     bool check_triangle_edge_shell =   (m_triangleEdge[tes[j]][0]==i) 
00489                                                     || (m_triangleEdge[tes[j]][1]==i) 
00490                                                     || (m_triangleEdge[tes[j]][2]==i);
00491                     if(!check_triangle_edge_shell)
00492                     {
00493                         std::cout << "*** CHECK FAILED : check_triangle_edge_shell, i = " << i << " , j = " << j << std::endl;
00494                         ret = false;                
00495                     }
00496                 }
00497             }       
00498         }
00499 
00500         return ret && EdgeSetTopologyContainer::checkTopology();
00501     #else
00502         return true;
00503     #endif
00504     }
00505 
00506     bool TriangleSetTopologyContainer::hasTriangles() const 
00507     {
00508         return !m_triangle.empty();
00509     }
00510 
00511     bool TriangleSetTopologyContainer::hasTriangleEdges() const 
00512     {
00513         return !m_triangleEdge.empty();
00514     }
00515 
00516     bool TriangleSetTopologyContainer::hasTriangleVertexShell() const 
00517     {
00518         return !m_triangleVertexShell.empty();
00519     }
00520 
00521     bool TriangleSetTopologyContainer::hasTriangleEdgeShell() const 
00522     {
00523         return !m_triangleEdgeShell.empty();
00524     }
00525 
00526     void TriangleSetTopologyContainer::clearTriangleVertexShell()
00527     {
00528         for(unsigned int i=0; i<m_triangleVertexShell.size(); ++i)
00529             m_triangleVertexShell[i].clear();
00530 
00531         m_triangleVertexShell.clear();
00532     }
00533 
00534     void TriangleSetTopologyContainer::clearTriangleEdgeShell()
00535     {
00536         for(unsigned int i=0; i<m_triangleEdgeShell.size(); ++i)
00537             m_triangleEdgeShell[i].clear();
00538 
00539         m_triangleEdgeShell.clear();
00540     }
00541 
00542     void TriangleSetTopologyContainer::clearTriangleEdges()
00543     {
00544         m_triangleEdge.clear();
00545     }
00546 
00547     void TriangleSetTopologyContainer::clearTriangles()
00548     {
00549         m_triangle.clear();
00550     }
00551 
00552     void TriangleSetTopologyContainer::clear()
00553     {
00554         clearTriangleVertexShell();
00555         clearTriangleEdgeShell();
00556         clearTriangleEdges();
00557         clearTriangles();
00558         EdgeSetTopologyContainer::clear();
00559     }
00560 
00561     void snapping_test_triangle(double epsilon, double alpha0, double alpha1, double alpha2,
00562                                 bool& is_snap_0, bool& is_snap_1, bool& is_snap_2)
00563     {
00564         is_snap_0=false;
00565         is_snap_1=false;
00566         is_snap_2=false;
00567 
00568         if(alpha0>=alpha1 && alpha0>=alpha2)
00569         {
00570             is_snap_0=(alpha1+alpha2<epsilon);
00571         }
00572         else
00573         {
00574             if(alpha1>=alpha0 && alpha1>=alpha2)
00575             {
00576                 is_snap_1=(alpha0+alpha2<epsilon);
00577             }
00578             else // alpha2>=alpha0 && alpha2>=alpha1
00579             { 
00580                 is_snap_2=(alpha0+alpha1<epsilon);
00581             }
00582         }
00583     }
00584 
00585     void snapping_test_edge(double epsilon, double alpha0, double alpha1, 
00586                             bool& is_snap_0, bool& is_snap_1)
00587     {
00588         is_snap_0=false;
00589         is_snap_1=false;
00590             
00591         if(alpha0>=alpha1)
00592         {
00593             is_snap_0=(alpha1<epsilon);
00594         }
00595         else // alpha1>=alpha0
00596         { 
00597             is_snap_1=(alpha0<epsilon);
00598         }
00599     }
00600     
00601 } // namespace topology
00602 
00603 } // namespace component
00604 
00605 } // namespace sofa

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