TriangleSetTopologyModifier.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/TriangleSetTopologyModifier.h>
00026 #include <sofa/component/topology/TriangleSetTopologyChange.h>
00027 #include <sofa/component/topology/TriangleSetTopologyContainer.h>
00028 #include <algorithm>
00029 #include <functional>
00030 #include <iostream>
00031 #include <sofa/core/ObjectFactory.h>
00032 
00033 namespace sofa
00034 {
00035 
00036 namespace component
00037 {
00038 
00039 namespace topology
00040 {
00041   SOFA_DECL_CLASS(TriangleSetTopologyModifier)
00042         int TriangleSetTopologyModifierClass = core::RegisterObject("Triangle set topology modifier")   
00043     .add< TriangleSetTopologyModifier >()
00044     ;
00045 
00046     using namespace std;
00047     using namespace sofa::defaulttype;      
00048 
00049 
00050     void TriangleSetTopologyModifier::init()
00051     {
00052         EdgeSetTopologyModifier::init();
00053         this->getContext()->get(m_container);
00054     }
00055 
00056 
00057     void TriangleSetTopologyModifier::addTriangleProcess(Triangle t)
00058     {
00059     #ifndef NDEBUG
00060         // check if the 3 vertices are different
00061         if((t[0]==t[1]) || (t[0]==t[2]) || (t[1]==t[2]) ) 
00062         {
00063             cout << "Error: [TriangleSetTopologyModifier::addTriangle] : invalid quad: " 
00064                 << t[0] << ", " << t[1] << ", " << t[2] <<  endl;
00065 
00066             return;
00067         }
00068 
00069         // check if there already exists a triangle with the same indices
00070         // Important: getEdgeIndex creates the quad vertex shell array
00071         if(m_container->hasTriangleVertexShell())
00072         {
00073             if(m_container->getTriangleIndex(t[0],t[1],t[2]) != -1)
00074             {
00075                 cout << "Error: [TriangleSetTopologyModifier::addTriangle] : Triangle " 
00076                     << t[0] << ", " << t[1] << ", " << t[2] << " already exists." << endl;
00077                 return;
00078             }
00079         }
00080     #endif
00081 
00082         const unsigned int triangleIndex = m_container->getNumberOfTriangles();
00083 
00084         if(m_container->hasTriangleVertexShell()) 
00085         {
00086             for(unsigned int j=0; j<3; ++j) 
00087             {
00088                 sofa::helper::vector< unsigned int > &shell = m_container->getTriangleVertexShellForModification( t[j] );
00089                 shell.push_back( triangleIndex );           
00090             }
00091         }
00092 
00093         if(m_container->hasEdges())
00094         {
00095             for(unsigned int j=0; j<3; ++j) 
00096             {
00097                 int edgeIndex = m_container->getEdgeIndex(t[(j+1)%3], t[(j+2)%3]);        
00098 
00099                 if(edgeIndex == -1)
00100                 {
00101                     // first create the edges
00102                     sofa::helper::vector< Edge > v(1);
00103                     Edge e1 (t[(j+1)%3], t[(j+2)%3]);
00104                     v[0] = e1;
00105 
00106                     addEdgesProcess((const sofa::helper::vector< Edge > &) v);
00107 
00108                     edgeIndex = m_container->getEdgeIndex(t[(j+1)%3],t[(j+2)%3]);
00109                     sofa::helper::vector< unsigned int > edgeIndexList;
00110                     edgeIndexList.push_back((unsigned int) edgeIndex);
00111                     addEdgesWarning( v.size(), v, edgeIndexList);
00112                 }
00113 
00114                 if(m_container->hasTriangleEdges())
00115                 {
00116                     m_container->m_triangleEdge.resize(triangleIndex+1);
00117                     m_container->m_triangleEdge[triangleIndex][j]= edgeIndex; 
00118                 }
00119 
00120                 if(m_container->hasTriangleEdgeShell()) 
00121                 {
00122                     sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[m_container->m_triangleEdge[triangleIndex][j]];
00123                     shell.push_back( triangleIndex );               
00124                 }
00125             }
00126         }
00127 
00128         m_container->m_triangle.push_back(t);
00129     }
00130 
00131 
00132     void TriangleSetTopologyModifier::addTrianglesProcess(const sofa::helper::vector< Triangle > &triangles) 
00133     {
00134         m_container->m_triangle.reserve(m_container->m_triangle.size() + triangles.size());
00135 
00136         for(unsigned int i=0; i<triangles.size(); ++i)
00137         {           
00138             addTriangleProcess(triangles[i]);
00139         }
00140     }
00141 
00142 
00143     void TriangleSetTopologyModifier::addTrianglesWarning(const unsigned int nTriangles, 
00144         const sofa::helper::vector< Triangle >& trianglesList,
00145         const sofa::helper::vector< unsigned int >& trianglesIndexList) 
00146     {
00147         // Warning that quads just got created
00148         TrianglesAdded *e = new TrianglesAdded(nTriangles, trianglesList, trianglesIndexList);
00149         addTopologyChange(e);
00150     }
00151 
00152 
00153     void TriangleSetTopologyModifier::addTrianglesWarning(const unsigned int nTriangles, 
00154         const sofa::helper::vector< Triangle >& trianglesList,
00155         const sofa::helper::vector< unsigned int >& trianglesIndexList,
00156         const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00157         const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs) 
00158     {
00159         // Warning that triangles just got created
00160         TrianglesAdded *e=new TrianglesAdded(nTriangles, trianglesList,trianglesIndexList,ancestors,baryCoefs);
00161         addTopologyChange(e);
00162     }
00163 
00164 
00165     void TriangleSetTopologyModifier::removeTrianglesWarning( sofa::helper::vector<unsigned int> &triangles) 
00166     {
00168         std::sort( triangles.begin(), triangles.end(), std::greater<unsigned int>() );
00169 
00170         // Warning that these triangles will be deleted
00171         TrianglesRemoved *e=new TrianglesRemoved(triangles);
00172         addTopologyChange(e);
00173     }       
00174 
00175 
00176     void TriangleSetTopologyModifier::removeTrianglesProcess(const sofa::helper::vector<unsigned int> &indices,
00177                                                                         const bool removeIsolatedEdges, 
00178                                                                         const bool removeIsolatedPoints)
00179     {       
00180         if(!m_container->hasTriangles()) // this method should only be called when triangles exist
00181         {
00182     #ifndef NDEBUG
00183             cout << "Error. [TriangleSetTopologyModifier::removeTrianglesProcess] triangle array is empty." << endl;
00184     #endif
00185             return;
00186         }
00187 
00188         if(m_container->hasEdges() && removeIsolatedEdges)
00189         {
00190             if(!m_container->hasTriangleEdges())
00191                 m_container->createTriangleEdgeArray();
00192 
00193             if(!m_container->hasTriangleEdgeShell())
00194                 m_container->createTriangleEdgeShellArray();
00195         }
00196 
00197         if(removeIsolatedPoints)
00198         {
00199             if(!m_container->hasTriangleVertexShell())
00200                 m_container->createTriangleVertexShellArray();
00201         }
00202 
00203         sofa::helper::vector<unsigned int> edgeToBeRemoved;
00204         sofa::helper::vector<unsigned int> vertexToBeRemoved;
00205 
00206         unsigned int lastTriangle = m_container->getNumberOfTriangles() - 1;
00207         for(unsigned int i = 0; i<indices.size(); ++i, --lastTriangle)
00208         {           
00209             Triangle &t = m_container->m_triangle[ indices[i] ];
00210             Triangle &q = m_container->m_triangle[ lastTriangle ];
00211 
00212             if(m_container->hasTriangleVertexShell())
00213             {
00214                 for(unsigned int j=0; j<3; ++j)
00215                 {
00216                     sofa::helper::vector< unsigned int > &shell = m_container->m_triangleVertexShell[ t[j] ];
00217                     shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00218                     if(removeIsolatedPoints && shell.empty())
00219                         vertexToBeRemoved.push_back(t[j]);
00220                 }
00221             }           
00222 
00223             if(m_container->hasTriangleEdgeShell()) 
00224             {
00225                 for(unsigned int j=0; j<3; ++j)
00226                 {
00227                     sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[ m_container->m_triangleEdge[indices[i]][j]];
00228                     shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00229                     if(removeIsolatedEdges && shell.empty())
00230                         edgeToBeRemoved.push_back(m_container->m_triangleEdge[indices[i]][j]);
00231                 }
00232             }           
00233 
00234             if(indices[i] < lastTriangle)
00235             {
00236                 if(m_container->hasTriangleVertexShell()) 
00237                 {
00238                     for(unsigned int j=0; j<3; ++j)
00239                     {
00240                         sofa::helper::vector< unsigned int > &shell = m_container->m_triangleVertexShell[ q[j] ];
00241                         replace(shell.begin(), shell.end(), lastTriangle, indices[i]);                  
00242                     }
00243                 }
00244 
00245                 if(m_container->hasTriangleEdgeShell()) 
00246                 {
00247                     for(unsigned int j=0; j<3; ++j)
00248                     {
00249                         sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[ m_container->m_triangleEdge[lastTriangle][j]];
00250                         replace(shell.begin(), shell.end(), lastTriangle, indices[i]);                  
00251                     }
00252                 }
00253             }           
00254 
00255             // removes the triangleEdges from the triangleEdgesArray
00256             if(m_container->hasTriangleEdges()) 
00257             {
00258                 m_container->m_triangleEdge[ indices[i] ] = m_container->m_triangleEdge[ lastTriangle ]; // overwriting with last valid value.
00259                 m_container->m_triangleEdge.resize( lastTriangle ); // resizing to erase multiple occurence of the triangle.
00260             }
00261 
00262             // removes the triangle from the triangleArray
00263             m_container->m_triangle[ indices[i] ] = m_container->m_triangle[ lastTriangle ]; // overwriting with last valid value.
00264             m_container->m_triangle.resize( lastTriangle ); // resizing to erase multiple occurence of the triangle.            
00265         }
00266 
00267         if(!edgeToBeRemoved.empty()) 
00268         {               
00270             removeEdgesWarning(edgeToBeRemoved);                
00271             propagateTopologicalChanges();              
00273             removeEdgesProcess(edgeToBeRemoved, false);             
00274         }
00275 
00276         if(!vertexToBeRemoved.empty())
00277         {               
00278             removePointsWarning(vertexToBeRemoved);             
00280             propagateTopologicalChanges();              
00281             removePointsProcess(vertexToBeRemoved);             
00282         }
00283     }
00284 
00285     void TriangleSetTopologyModifier::addPointsProcess(const unsigned int nPoints) 
00286     {
00287         // start by calling the parent's method.
00288         EdgeSetTopologyModifier::addPointsProcess( nPoints );
00289 
00290         // now update the local container structures.
00291         if(m_container->hasTriangleVertexShell())
00292             m_container->m_triangleVertexShell.resize( m_container->getNbPoints() );
00293     }
00294 
00295     void TriangleSetTopologyModifier::addEdgesProcess(const sofa::helper::vector< Edge > &edges) 
00296     {
00297         if(!m_container->hasEdges())
00298         {
00299             m_container->createEdgeSetArray();
00300         }
00301 
00302         // start by calling the parent's method.
00303         EdgeSetTopologyModifier::addEdgesProcess( edges );
00304 
00305         if(m_container->hasTriangleEdgeShell())
00306             m_container->m_triangleEdgeShell.resize( m_container->m_triangleEdgeShell.size() + edges.size() );
00307     }
00308 
00309     void TriangleSetTopologyModifier::removePointsProcess( sofa::helper::vector<unsigned int> &indices, 
00310                                                                         const bool removeDOF) 
00311     {   
00312         if(m_container->hasTriangles())
00313         {
00314             if(!m_container->hasTriangleVertexShell())
00315                 m_container->createTriangleVertexShellArray();  
00316 
00317             unsigned int lastPoint = m_container->getNbPoints() - 1;
00318             for(unsigned int i=0; i<indices.size(); ++i, --lastPoint)
00319             {
00320                 // updating the triangles connected to the point replacing the removed one:
00321                 // for all triangles connected to the last point
00322 
00323                 sofa::helper::vector<unsigned int> &shell = m_container->m_triangleVertexShell[lastPoint];
00324                 for(unsigned int j=0; j<shell.size(); ++j) 
00325                 {
00326                     const unsigned int q = shell[j];
00327                     for(unsigned int k=0; k<3; ++k)
00328                     {
00329                         if(m_container->m_triangle[q][k] == lastPoint)
00330                             m_container->m_triangle[q][k] = indices[i];
00331                     }
00332                 }
00333 
00334                 // updating the edge shell itself (change the old index for the new one)
00335                 m_container->m_triangleVertexShell[ indices[i] ] = m_container->m_triangleVertexShell[ lastPoint ];
00336             }
00337 
00338             m_container->m_triangleVertexShell.resize( m_container->m_triangleVertexShell.size() - indices.size() );
00339         }
00340 
00341         // Important : the points are actually deleted from the mechanical object's state vectors iff (removeDOF == true)
00342         // call the parent's method.
00343         EdgeSetTopologyModifier::removePointsProcess( indices, removeDOF );
00344     }
00345 
00346     void TriangleSetTopologyModifier::removeEdgesProcess( const sofa::helper::vector<unsigned int> &indices,
00347                                                                     const bool removeIsolatedItems) 
00348     {           
00349         // Note: this does not check if an edge is removed from an existing triangle (it should never happen)
00350 
00351         if(m_container->hasTriangleEdges()) // this method should only be called when edges exist
00352         {
00353             if(!m_container->hasTriangleEdgeShell())
00354                 m_container->createTriangleEdgeShellArray();
00355 
00356             unsigned int lastEdge = m_container->getNumberOfEdges() - 1;
00357             for(unsigned int i = 0; i < indices.size(); ++i, --lastEdge)
00358             {
00359                 // updating the triangles connected to the edge replacing the removed one:
00360                 // for all triangles connected to the last point
00361                 for(sofa::helper::vector<unsigned int>::iterator itt = m_container->m_triangleEdgeShell[lastEdge].begin();
00362                     itt != m_container->m_triangleEdgeShell[lastEdge].end(); ++itt) 
00363                 {
00364                     unsigned int edgeIndex = m_container->getEdgeIndexInTriangle(m_container->m_triangleEdge[(*itt)], lastEdge);
00365                     m_container->m_triangleEdge[(*itt)][edgeIndex] = indices[i];
00366                 }
00367 
00368                 // updating the edge shell itself (change the old index for the new one)
00369                 m_container->m_triangleEdgeShell[ indices[i] ] = m_container->m_triangleEdgeShell[ lastEdge ];
00370             }
00371 
00372             m_container->m_triangleEdgeShell.resize( m_container->m_triangleEdgeShell.size() - indices.size() );
00373         }
00374 
00375         // call the parent's method.
00376         EdgeSetTopologyModifier::removeEdgesProcess(indices, removeIsolatedItems);
00377     }
00378 
00379     void TriangleSetTopologyModifier::renumberPointsProcess( const sofa::helper::vector<unsigned int> &index, 
00380                                                                         const sofa::helper::vector<unsigned int> &inv_index, 
00381                                                                         const bool renumberDOF) 
00382     {
00383         if(m_container->hasTriangles())
00384         {
00385             if(m_container->hasTriangleVertexShell())
00386             {
00387                 sofa::helper::vector< sofa::helper::vector< unsigned int > > triangleVertexShell_cp = m_container->m_triangleVertexShell;
00388                 for(unsigned int i=0; i<index.size(); ++i)
00389                 {
00390                     m_container->m_triangleVertexShell[i] = triangleVertexShell_cp[ index[i] ];
00391                 }
00392             }
00393 
00394             for(unsigned int i=0; i<m_container->m_triangle.size(); ++i)
00395             {
00396                 m_container->m_triangle[i][0] = inv_index[ m_container->m_triangle[i][0] ];
00397                 m_container->m_triangle[i][1] = inv_index[ m_container->m_triangle[i][1] ];
00398                 m_container->m_triangle[i][2] = inv_index[ m_container->m_triangle[i][2] ];
00399             }
00400         }
00401 
00402         // call the parent's method
00403         EdgeSetTopologyModifier::renumberPointsProcess( index, inv_index, renumberDOF );
00404     }  
00405 
00406     void TriangleSetTopologyModifier::removeTriangles(sofa::helper::vector< unsigned int >& triangles, 
00407                                                                     const bool removeIsolatedEdges, 
00408                                                                     const bool removeIsolatedPoints)
00409     {
00411         removeTrianglesWarning(triangles);
00412         // inform other objects that the triangles are going to be removed
00413         propagateTopologicalChanges();
00414         // now destroy the old triangles.
00415         removeTrianglesProcess(  triangles ,removeIsolatedEdges, removeIsolatedPoints);
00416 
00417         m_container->checkTopology();   
00418     }
00419 
00420     void TriangleSetTopologyModifier::removeItems(sofa::helper::vector< unsigned int >& items)
00421     {
00422         removeTriangles(items, true, true);
00423     }
00424 
00425     void TriangleSetTopologyModifier::renumberPoints( const sofa::helper::vector<unsigned int> &index, 
00426         const sofa::helper::vector<unsigned int> &inv_index)
00427     {   
00429         renumberPointsWarning(index, inv_index);
00430         // inform other objects that the triangles are going to be removed
00431         propagateTopologicalChanges();
00432         // now renumber the points      
00433         renumberPointsProcess(index, inv_index);
00434 
00435         m_container->checkTopology();             
00436     }
00437 
00438 
00439 } // namespace topology
00440 
00441 } // namespace component
00442 
00443 } // namespace sofa
00444 

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