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

Generated on Sun Nov 23 03:45:50 2008 for Sofa by  doxygen 1.5.7.1