EdgeSetTopologyModifier.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/EdgeSetTopologyModifier.h>
00026 #include <sofa/component/topology/EdgeSetTopologyChange.h>
00027 #include <sofa/component/topology/EdgeSetTopologyContainer.h>
00028 #include <algorithm>
00029 #include <functional>
00030 #include <iostream>
00031 #include <sofa/core/ObjectFactory.h>
00032 
00033 
00034 // Use BOOST GRAPH LIBRARY : 
00035 
00036 #include <boost/config.hpp>
00037 #include <iostream>
00038 #include <vector>
00039 #include <utility>
00040 
00041 #include <boost/graph/adjacency_list.hpp>
00042 #include <boost/graph/connected_components.hpp>
00043 
00044 #include <boost/graph/cuthill_mckee_ordering.hpp>
00045 #include <boost/graph/bandwidth.hpp>
00046 
00047 namespace sofa
00048 {
00049 
00050 namespace component
00051 {
00052 
00053 namespace topology
00054 {
00055     using namespace sofa::defaulttype;
00056   SOFA_DECL_CLASS(EdgeSetTopologyModifier)
00057         int EdgeSetTopologyModifierClass = core::RegisterObject("Edge set topology modifier")
00058       .add< EdgeSetTopologyModifier >();    
00059 
00060     using namespace std;
00061     using namespace sofa::defaulttype;
00062     using namespace sofa::core::componentmodel::behavior;
00063 
00064     void EdgeSetTopologyModifier::init()
00065     {
00066         PointSetTopologyModifier::init();
00067         getContext()->get(m_container);
00068     }
00069     
00070     void EdgeSetTopologyModifier::addEdgeProcess(Edge e)
00071     {   
00072 #ifndef NDEBUG
00073         // check if the 2 vertices are different
00074         if(e[0] == e[1])
00075         {
00076             cout << "Error: [EdgeSetTopologyModifier::addEdge] : invalid edge: " 
00077                  << e[0] << ", " << e[1] << endl;
00078 
00079             return;
00080         }
00081 
00082         // check if there already exists an edge. 
00083         // Important: getEdgeIndex creates the edge vertex shell array
00084         if(m_container->hasEdgeVertexShell())
00085         {
00086             if(m_container->getEdgeIndex(e[0],e[1]) != -1)
00087             {
00088                 cout << "Error: [EdgeSetTopologyModifier::addEdgesProcess] : Edge " 
00089                      << e[0] << ", " << e[1] << " already exists." << endl;
00090                 return;
00091             }
00092         }
00093 #endif
00094         if (m_container->hasEdgeVertexShell()) 
00095         {     
00096             const unsigned int edgeId = m_container->getNumberOfEdges();
00097 
00098             sofa::helper::vector< unsigned int > &shell0 = m_container->getEdgeVertexShellForModification( e[0] );
00099             shell0.push_back(edgeId);           
00100 
00101             sofa::helper::vector< unsigned int > &shell1 = m_container->getEdgeVertexShellForModification( e[1] );
00102             shell1.push_back(edgeId);           
00103         }
00104 
00105         m_container->m_edge.push_back(e);
00106     }
00107 
00108     
00109     void EdgeSetTopologyModifier::addEdgesProcess(const sofa::helper::vector< Edge > &edges) 
00110     {
00111         for (unsigned int i=0; i<edges.size(); ++i)
00112         {
00113             addEdgeProcess(edges[i]);
00114         }
00115     }
00116 
00117     
00118     void EdgeSetTopologyModifier::addEdgesWarning(const unsigned int nEdges) 
00119     {
00120         // Warning that edges just got created
00121         EdgesAdded *e = new EdgesAdded(nEdges);
00122         addTopologyChange(e);
00123     }
00124 
00125     
00126     void EdgeSetTopologyModifier::addEdgesWarning(const unsigned int nEdges, 
00127         const sofa::helper::vector< Edge >& edgesList,
00128         const sofa::helper::vector< unsigned int >& edgesIndexList) 
00129     {
00130         // Warning that edges just got created
00131         EdgesAdded *e = new EdgesAdded(nEdges, edgesList, edgesIndexList);
00132         addTopologyChange(e);
00133     }
00134 
00135     
00136     void EdgeSetTopologyModifier::addEdgesWarning(const unsigned int nEdges, 
00137         const sofa::helper::vector< Edge >& edgesList,
00138         const sofa::helper::vector< unsigned int >& edgesIndexList,
00139         const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors) 
00140     {
00141         // Warning that edges just got created
00142         EdgesAdded *e = new EdgesAdded(nEdges, edgesList, edgesIndexList, ancestors);
00143         addTopologyChange(e);
00144     }
00145 
00146     
00147     void EdgeSetTopologyModifier::addEdgesWarning(const unsigned int nEdges, 
00148         const sofa::helper::vector< Edge >& edgesList,
00149         const sofa::helper::vector< unsigned int >& edgesIndexList,
00150         const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00151         const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs) 
00152     {
00153         // Warning that edges just got created
00154         EdgesAdded *e = new EdgesAdded(nEdges, edgesList, edgesIndexList, ancestors, baryCoefs);
00155         addTopologyChange(e);
00156     }
00157 
00158     
00159     void EdgeSetTopologyModifier::removeEdgesWarning(sofa::helper::vector<unsigned int> &edges ) 
00160     {
00161         // sort edges to remove in a descendent order
00162         std::sort( edges.begin(), edges.end(), std::greater<unsigned int>() );  
00163 
00164         // Warning that these edges will be deleted
00165         EdgesRemoved *e = new EdgesRemoved(edges);
00166         addTopologyChange(e);
00167     }
00168 
00169     
00170     void EdgeSetTopologyModifier::removeEdgesProcess(const sofa::helper::vector<unsigned int> &indices,
00171                                                                 const bool removeIsolatedItems)
00172     {
00173         if(!m_container->hasEdges())    // this method should only be called when edges exist
00174         {
00175             cout << "Warning. [EdgeSetTopologyModifier::removeEdgesProcess] edge array is empty." << endl;
00176             return;
00177         }
00178 
00179         if(removeIsolatedItems && !m_container->hasEdgeVertexShell()) 
00180         {
00181             m_container->createEdgeVertexShellArray();
00182         }
00183 
00184         sofa::helper::vector<unsigned int> vertexToBeRemoved;
00185 
00186         unsigned int lastEdgeIndex = m_container->getNumberOfEdges() - 1;
00187         for (unsigned int i=0; i<indices.size(); ++i, --lastEdgeIndex)
00188         {
00189             // now updates the shell information of the edge formely at the end of the array
00190             if(m_container->hasEdgeVertexShell())
00191             {
00192                 const Edge &e = m_container->m_edge[ indices[i] ];
00193                 const Edge &q = m_container->m_edge[ lastEdgeIndex ];
00194                 const unsigned int point0 = e[0], point1 = e[1];
00195                 const unsigned int point2 = q[0], point3 = q[1];
00196 
00197                 sofa::helper::vector< unsigned int > &shell0 = m_container->m_edgeVertexShell[ point0 ];
00198                 shell0.erase( std::remove( shell0.begin(), shell0.end(), indices[i] ), shell0.end() );
00199                 if(removeIsolatedItems && shell0.empty()) 
00200                 {
00201                     vertexToBeRemoved.push_back(point0);
00202                 }
00203 
00204                 sofa::helper::vector< unsigned int > &shell1 = m_container->m_edgeVertexShell[ point1 ];
00205                 shell1.erase( std::remove( shell1.begin(), shell1.end(), indices[i] ), shell1.end() );
00206                 if(removeIsolatedItems && shell1.empty()) 
00207                 {
00208                     vertexToBeRemoved.push_back(point1);
00209                 }
00210 
00211                 if(indices[i] < lastEdgeIndex)
00212                 {
00213                     //replaces the edge index oldEdgeIndex with indices[i] for the first vertex
00214                     sofa::helper::vector< unsigned int > &shell2 = m_container->m_edgeVertexShell[ point2 ];
00215                     replace(shell2.begin(), shell2.end(), lastEdgeIndex, indices[i]);           
00216 
00217                     //replaces the edge index oldEdgeIndex with indices[i] for the second vertex
00218                     sofa::helper::vector< unsigned int > &shell3 = m_container->m_edgeVertexShell[ point3 ];
00219                     replace(shell3.begin(), shell3.end(), lastEdgeIndex, indices[i]);
00220                 }
00221             }
00222 
00223             // removes the edge from the edgelist
00224             m_container->m_edge[ indices[i] ] = m_container->m_edge[ lastEdgeIndex ]; // overwriting with last valid value.
00225             m_container->m_edge.resize( lastEdgeIndex ); // resizing to erase multiple occurence of the edge.
00226         }
00227 
00228         if (! vertexToBeRemoved.empty()) 
00229         {
00230             removePointsWarning(vertexToBeRemoved);
00231             // inform other objects that the points are going to be removed
00232             propagateTopologicalChanges();
00233             removePointsProcess(vertexToBeRemoved);
00234         }
00235     }
00236 
00237     void EdgeSetTopologyModifier::addPointsProcess(const unsigned int nPoints) 
00238     {
00239         // start by calling the parent's method.
00240         PointSetTopologyModifier::addPointsProcess( nPoints );      
00241 
00242         if(m_container->hasEdgeVertexShell())
00243             m_container->m_edgeVertexShell.resize( m_container->getNbPoints() );
00244     }
00245 
00246     void EdgeSetTopologyModifier::removePointsProcess(sofa::helper::vector<unsigned int> &indices, 
00247                                                                 const bool removeDOF) 
00248     {
00249         // Note: edges connected to the points being removed are not removed here (this situation should not occur)
00250 
00251         if(m_container->hasEdges())
00252         {
00253             // forces the construction of the edge shell array if it does not exists
00254             if(!m_container->hasEdgeVertexShell())
00255                 m_container->createEdgeVertexShellArray();
00256 
00257             unsigned int lastPoint = m_container->getNbPoints() - 1;
00258             for (unsigned int i=0; i<indices.size(); ++i, --lastPoint)
00259             {
00260                 // updating the edges connected to the point replacing the removed one:
00261                 // for all edges connected to the last point
00262                 for (unsigned int j=0; j<m_container->m_edgeVertexShell[lastPoint].size(); ++j)
00263                 {
00264                     const int edgeId = m_container->m_edgeVertexShell[lastPoint][j];
00265                     // change the old index for the new one
00266                     if ( m_container->m_edge[ edgeId ][0] == lastPoint )
00267                         m_container->m_edge[ edgeId ][0] = indices[i];
00268                     else
00269                         m_container->m_edge[ edgeId ][1] = indices[i];
00270                 }
00271 
00272                 // updating the edge shell itself (change the old index for the new one)
00273                 m_container->m_edgeVertexShell[ indices[i] ] = m_container->m_edgeVertexShell[ lastPoint ];
00274             }
00275 
00276             m_container->m_edgeVertexShell.resize( m_container->m_edgeVertexShell.size() - indices.size() );
00277         }
00278 
00279         // Important : the points are actually deleted from the mechanical object's state vectors iff (removeDOF == true)
00280         // call the parent method.
00281         PointSetTopologyModifier::removePointsProcess( indices, removeDOF );
00282     }
00283 
00284     void EdgeSetTopologyModifier::renumberPointsProcess( const sofa::helper::vector<unsigned int> &index, 
00285                                                                     const sofa::helper::vector<unsigned int> &inv_index, 
00286                                                                     const bool renumberDOF) 
00287     {
00288         if(m_container->hasEdges())
00289         {
00290             if(m_container->hasEdgeVertexShell())
00291             {
00292                 // copy of the the edge vertex shell array
00293                 sofa::helper::vector< sofa::helper::vector< unsigned int > > edgeVertexShell_cp = m_container->getEdgeVertexShellArray();
00294 
00295                 for (unsigned int i=0; i<index.size(); ++i)
00296                 {
00297                     m_container->m_edgeVertexShell[i] = edgeVertexShell_cp[ index[i] ];
00298                 }
00299             }
00300 
00301             for (unsigned int i=0; i<m_container->m_edge.size(); ++i)
00302             {
00303                 const unsigned int p0 = inv_index[ m_container->m_edge[i][0]  ];
00304                 const unsigned int p1 = inv_index[ m_container->m_edge[i][1]  ];
00305 
00306                 if(p0<p1)
00307                 {
00308                     m_container->m_edge[i][0] = p0;
00309                     m_container->m_edge[i][1] = p1;
00310                 }
00311                 else
00312                 {
00313                     m_container->m_edge[i][0] = p1;
00314                     m_container->m_edge[i][1] = p0;
00315                 }
00316             }
00317         }
00318 
00319         // call the parent method    
00320         PointSetTopologyModifier::renumberPointsProcess( index, inv_index, renumberDOF );   
00321     }
00322 
00323     
00324     void EdgeSetTopologyModifier::swapEdgesProcess(const sofa::helper::vector< sofa::helper::vector< unsigned int > >& edgesPairs)
00325     {
00326         if(!m_container->hasEdges())
00327             return;
00328 
00329         // first create the edges
00330         sofa::helper::vector< Edge > v;
00331         v.reserve(2*edgesPairs.size());
00332 
00333         sofa::helper::vector< unsigned int > edgeIndexList;
00334         edgeIndexList.reserve(2*edgesPairs.size());
00335 
00336         sofa::helper::vector<sofa::helper::vector<unsigned int> > ancestorsArray;
00337         ancestorsArray.reserve(edgesPairs.size());
00338 
00339         unsigned int nbEdges = m_container->getNumberOfEdges();
00340 
00341         for (unsigned int i=0; i<edgesPairs.size(); ++i)
00342         {         
00343             const unsigned int i1 = edgesPairs[i][0];
00344             const unsigned int i2 = edgesPairs[i][1];       
00345 
00346             const unsigned int p11 = m_container->getEdge(i1)[0];
00347             const unsigned int p12 = m_container->getEdge(i1)[1];
00348             const unsigned int p21 = m_container->getEdge(i2)[0]; 
00349             const unsigned int p22 = m_container->getEdge(i2)[1];       
00350 
00351             const Edge e1(p11, p21), e2(p12, p22);
00352 
00353             v.push_back(e1);
00354             v.push_back(e2);
00355             edgeIndexList.push_back(nbEdges);
00356             edgeIndexList.push_back(nbEdges+1);
00357             nbEdges += 2;
00358 
00359             sofa::helper::vector<unsigned int> ancestors(2);
00360             ancestors[0] = i1;
00361             ancestors[1] = i2;
00362             ancestorsArray.push_back(ancestors);        
00363         }
00364 
00365         addEdgesProcess( v );
00366 
00367         // now warn about the creation
00368         addEdgesWarning( v.size(), v, edgeIndexList, ancestorsArray);
00369 
00370         // now warn about the destruction of the old edges
00371         sofa::helper::vector< unsigned int > indices;
00372         indices.reserve(2*edgesPairs.size());
00373         for (unsigned int i=0; i<edgesPairs.size(); ++i)
00374         {
00375             indices.push_back( edgesPairs[i][0]  );
00376             indices.push_back( edgesPairs[i][1] );
00377         }
00378         removeEdgesWarning(indices );
00379 
00380         // propagate the warnings
00381         propagateTopologicalChanges();
00382 
00383         // now destroy the old edges.   
00384         removeEdgesProcess( indices );      
00385     }
00386 
00387     
00388     void EdgeSetTopologyModifier::fuseEdgesProcess(const sofa::helper::vector< sofa::helper::vector< unsigned int > >& edgesPairs, 
00389                                                                 const bool removeIsolatedPoints)
00390     {
00391         if(!m_container->hasEdges())
00392             return;
00393 
00394         // first create the edges
00395         sofa::helper::vector< Edge > v;
00396         v.reserve(edgesPairs.size());
00397 
00398         sofa::helper::vector< unsigned int > edgeIndexList;
00399         edgeIndexList.reserve(edgesPairs.size());
00400 
00401         sofa::helper::vector<sofa::helper::vector<unsigned int> > ancestorsArray;
00402         ancestorsArray.reserve(edgesPairs.size());
00403 
00404         unsigned int nbEdges=m_container->getNumberOfEdges();            
00405 
00406         for (unsigned int i=0; i<edgesPairs.size(); ++i)
00407         {               
00408             const unsigned int i1 = edgesPairs[i][0];
00409             const unsigned int i2 = edgesPairs[i][1];       
00410 
00411             unsigned int p11 = m_container->getEdge(i1)[0];
00412             unsigned int p22 = m_container->getEdge(i2)[1]; 
00413 
00414             if(p11 == p22)
00415             {
00416                 p11 = m_container->getEdge(i2)[0];  
00417                 p22 = m_container->getEdge(i1)[1]; 
00418             }
00419 
00420             const Edge e (p11, p22);          
00421             v.push_back(e);
00422 
00423             edgeIndexList.push_back(nbEdges);
00424             nbEdges += 1;
00425 
00426             sofa::helper::vector<unsigned int> ancestors(2);
00427             ancestors[0] = i1;
00428             ancestors[1] = i2;
00429             ancestorsArray.push_back(ancestors);        
00430         }
00431 
00432         addEdgesProcess( v );
00433 
00434         // now warn about the creation
00435         addEdgesWarning( v.size(), v, edgeIndexList, ancestorsArray);
00436 
00437         // now warn about the destruction of the old edges
00438         sofa::helper::vector< unsigned int > indices;
00439         indices.reserve(2*edgesPairs.size());
00440         for (unsigned int i=0; i<edgesPairs.size(); ++i)
00441         {
00442             indices.push_back( edgesPairs[i][0] );
00443             indices.push_back( edgesPairs[i][1] );
00444         }
00445 
00446         removeEdgesWarning( indices );
00447 
00448         // propagate the warnings
00449         propagateTopologicalChanges();
00450 
00451         // now destroy the old edges.   
00452         removeEdgesProcess( indices, removeIsolatedPoints );        
00453     }
00454 
00455     
00456     void EdgeSetTopologyModifier::splitEdgesProcess(sofa::helper::vector<unsigned int> &indices,
00457                                                                 const bool removeIsolatedPoints)
00458     {
00459         if(!m_container->hasEdges())
00460             return;
00461 
00462         sofa::helper::vector< sofa::helper::vector< double > > defaultBaryCoefs(indices.size());
00463 
00464         sofa::helper::vector< sofa::helper::vector< unsigned int > > v(indices.size()); 
00465 
00466         sofa::helper::vector< Edge >  edges;
00467         edges.reserve(2*indices.size());
00468 
00469         sofa::helper::vector< unsigned int >  edgesIndex;
00470         edgesIndex.reserve(2*indices.size());
00471 
00472         unsigned int nbEdges = m_container->getNumberOfEdges();
00473 
00474         for (unsigned int i=0; i<indices.size(); ++i)
00475         {
00476             const unsigned int p1 = m_container->getEdge( indices[i] )[0];
00477             const unsigned int p2 = m_container->getEdge( indices[i] )[1];
00478 
00479             // Adding the new point
00480             v[i].resize(2);
00481             v[i][0] = p1;
00482             v[i][1] = p2;
00483 
00484             // Adding the new Edges
00485             const Edge e1( p1, m_container->getNbPoints() + i );
00486             const Edge e2( m_container->getNbPoints() + i, p2 );
00487             edges.push_back( e1 );
00488             edges.push_back( e2 );
00489             edgesIndex.push_back(nbEdges++);
00490             edgesIndex.push_back(nbEdges++);
00491 
00492             defaultBaryCoefs[i].resize(2, 0.5f);
00493         }
00494 
00495         addPointsProcess( indices.size());
00496 
00497         addEdgesProcess( edges );
00498 
00499         // warn about added points and edges
00500         addPointsWarning( indices.size(), v, defaultBaryCoefs);
00501 
00502         addEdgesWarning( edges.size(), edges, edgesIndex);
00503 
00504         // warn about old edges about to be removed
00505         removeEdgesWarning( indices );
00506 
00507         propagateTopologicalChanges();
00508 
00509         // Removing the old edges
00510         removeEdgesProcess( indices, removeIsolatedPoints );
00511     }
00512 
00513     
00514     void EdgeSetTopologyModifier::splitEdgesProcess(sofa::helper::vector<unsigned int> &indices,
00515                                                                 const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs, 
00516                                                                 const bool removeIsolatedPoints)
00517     {
00518         if(!m_container->hasEdges())
00519             return;
00520 
00521         sofa::helper::vector< sofa::helper::vector< unsigned int > > v(indices.size());
00522 
00523         sofa::helper::vector< Edge >  edges;
00524         edges.reserve(2*indices.size());
00525 
00526         sofa::helper::vector< unsigned int >  edgesIndex;
00527         edgesIndex.reserve(2*indices.size());
00528 
00529         unsigned int nbEdges = m_container->getNumberOfEdges();
00530 
00531         for (unsigned int i=0; i<indices.size(); ++i)
00532         {
00533             const unsigned int p1 = m_container->getEdge( indices[i] )[0];
00534             const unsigned int p2 = m_container->getEdge( indices[i] )[1];
00535 
00536             // Adding the new point
00537             v[i].resize(2);
00538             v[i][0] = p1;
00539             v[i][1] = p2;
00540 
00541             // Adding the new Edges
00542             const Edge e1( p1, m_container->getNbPoints() + i );
00543             const Edge e2( m_container->getNbPoints() + i, p2 );
00544             edges.push_back( e1 );
00545             edges.push_back( e2 );
00546             edgesIndex.push_back(nbEdges++);
00547             edgesIndex.push_back(nbEdges++);
00548         }
00549 
00550         addPointsProcess( indices.size());
00551 
00552         addEdgesProcess( edges );
00553 
00554         // warn about added points and edges
00555         addPointsWarning( indices.size(), v, baryCoefs);
00556 
00557         addEdgesWarning( edges.size(), edges, edgesIndex);
00558 
00559         // warn about old edges about to be removed
00560         removeEdgesWarning( indices );
00561 
00562         propagateTopologicalChanges();
00563 
00564         // Removing the old edges
00565         removeEdgesProcess( indices, removeIsolatedPoints );
00566     }
00567 
00568     void EdgeSetTopologyModifier::removeEdges(sofa::helper::vector< unsigned int >& edges, 
00569                                                             const bool removeIsolatedPoints)
00570     {
00572         removeEdgesWarning(edges);
00573         // inform other objects that the edges are going to be removed
00574         propagateTopologicalChanges();
00575         // now destroy the old edges.
00576         removeEdgesProcess( edges, removeIsolatedPoints );
00577 
00578         m_container->checkTopology();
00579     }
00580 
00581     void EdgeSetTopologyModifier::removeItems(sofa::helper::vector< unsigned int >& items)
00582     {
00583         removeEdges(items);
00584     }
00585 
00586     void EdgeSetTopologyModifier::renumberPoints( const sofa::helper::vector<unsigned int> &index, 
00587                                                                 const sofa::helper::vector<unsigned int> &inv_index)
00588     {   
00590         renumberPointsWarning(index, inv_index);
00591         // inform other objects that the triangles are going to be removed
00592         propagateTopologicalChanges();
00593         // now renumber the points      
00594         renumberPointsProcess(index, inv_index);
00595 
00596         m_container->checkTopology();    
00597     }
00598 
00599     void EdgeSetTopologyModifier::addEdges(const sofa::helper::vector< Edge >& edges) 
00600     {
00601         unsigned int nEdges = m_container->getNumberOfEdges();
00602 
00604         addEdgesProcess(edges);
00605 
00606         sofa::helper::vector<unsigned int> edgesIndex;
00607         edgesIndex.reserve(edges.size());
00608 
00609         for (unsigned int i=0; i<edges.size(); ++i) 
00610         {
00611             edgesIndex.push_back(nEdges+i);
00612         }
00613 
00614         // add topology event in the stack of topological events
00615         addEdgesWarning( edges.size(), edges, edgesIndex);
00616 
00617         // inform other objects that the edges are already added
00618         propagateTopologicalChanges();
00619     }
00620 
00621     void EdgeSetTopologyModifier::addEdges(const sofa::helper::vector< Edge >& edges,
00622         const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00623         const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs) 
00624     {
00625         unsigned int nEdges = m_container->getNumberOfEdges();
00626 
00628         addEdgesProcess(edges);
00629 
00630         sofa::helper::vector<unsigned int> edgesIndex;
00631         edgesIndex.reserve(edges.size());
00632 
00633         for (unsigned int i=0; i<edges.size(); ++i) 
00634         {
00635             edgesIndex.push_back(nEdges+i);
00636         }
00637 
00638         // add topology event in the stack of topological events
00639         addEdgesWarning( edges.size(), edges, edgesIndex, ancestors, baryCoefs);
00640 
00641         // inform other objects that the edges are already added
00642         propagateTopologicalChanges();
00643     }
00644 
00645     void EdgeSetTopologyModifier::swapEdges(const sofa::helper::vector< sofa::helper::vector< unsigned int > >& edgesPairs)
00646     {
00647         swapEdgesProcess(edgesPairs);
00648         m_container->checkTopology();
00649     }
00650 
00651     void EdgeSetTopologyModifier::fuseEdges(const sofa::helper::vector< sofa::helper::vector< unsigned int > >& edgesPairs, const bool removeIsolatedPoints)
00652     {
00653         fuseEdgesProcess(edgesPairs, removeIsolatedPoints);
00654         m_container->checkTopology();
00655     }
00656 
00657     void EdgeSetTopologyModifier::splitEdges( sofa::helper::vector<unsigned int> &indices,
00658         const bool removeIsolatedPoints) 
00659     {
00660         splitEdgesProcess(indices, removeIsolatedPoints);
00661         m_container->checkTopology();
00662     }
00663 
00664     void EdgeSetTopologyModifier::splitEdges( sofa::helper::vector<unsigned int> &indices,
00665         const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs,
00666         const bool removeIsolatedPoints) 
00667     {
00668         splitEdgesProcess(indices, baryCoefs, removeIsolatedPoints);
00669         m_container->checkTopology();
00670     }
00671 
00672     // Give the optimal vertex permutation according to the Reverse CuthillMckee algorithm (use BOOST GRAPH LIBRAIRY)
00673     void EdgeSetTopologyModifier::resortCuthillMckee(sofa::helper::vector<int>& inverse_permutation)
00674     {
00675         using namespace boost;
00676         using namespace std;
00677         typedef adjacency_list<vecS, vecS, undirectedS, 
00678             property<vertex_color_t, default_color_type,
00679             property<vertex_degree_t,int> > > Graph;
00680         typedef graph_traits<Graph>::vertex_descriptor Vertex;
00681         typedef graph_traits<Graph>::vertices_size_type size_type;
00682 
00683         Graph G;
00684 
00685         const sofa::helper::vector<Edge> &ea=m_container->getEdgeArray();
00686 
00687         for (unsigned int k=0; k<ea.size(); ++k) 
00688         {
00689             add_edge(ea[k][0], ea[k][1], G);
00690         }
00691 
00692         inverse_permutation.resize(num_vertices(G));
00693 
00694         property_map<Graph, vertex_index_t>::type index_map = get(vertex_index, G);
00695 
00696         std::cout << "original bandwidth: " << bandwidth(G) << std::endl;
00697 
00698         std::vector<Vertex> inv_perm(num_vertices(G));
00699         std::vector<size_type> perm(num_vertices(G));
00700 
00701         //reverse cuthill_mckee_ordering
00702         cuthill_mckee_ordering(G, inv_perm.rbegin());
00703 
00704         //std::cout << "Reverse Cuthill-McKee ordering:" << endl;
00705         //std::cout << "  ";
00706         unsigned int ind_i = 0;
00707         for (std::vector<Vertex>::const_iterator it = inv_perm.begin();
00708             it != inv_perm.end(); ++it)
00709         {
00710                 //std::cout << index_map[*it] << " ";
00711                 inverse_permutation[ind_i++]=index_map[*it];
00712         }
00713         //std::cout << endl;
00714 
00715         for (size_type c=0; c!=inv_perm.size(); ++c)
00716             perm[index_map[inv_perm[c]]] = c;
00717 
00718         std::cout << "  bandwidth: " 
00719             << bandwidth(G, make_iterator_property_map(&perm[0], index_map, perm[0]))
00720             << std::endl;
00721     }
00722 
00723 
00724 } // namespace topology
00725 
00726 } // namespace component
00727 
00728 } // namespace sofa
00729 

Generated on Sun Nov 23 03:43:31 2008 for Sofa by  doxygen 1.5.7.1