ManifoldEdgeSetTopologyContainer.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 
00026 #include <sofa/component/topology/ManifoldEdgeSetTopologyContainer.h>
00027 
00028 #include <sofa/core/ObjectFactory.h>
00029 // Use BOOST GRAPH LIBRARY : 
00030 
00031 #include <boost/config.hpp>
00032 #include <iostream>
00033 #include <vector>
00034 #include <utility>
00035 
00036 #include <boost/graph/adjacency_list.hpp>
00037 #include <boost/graph/connected_components.hpp>
00038 
00039 #include <boost/graph/cuthill_mckee_ordering.hpp>
00040 #include <boost/graph/bandwidth.hpp>
00041 
00042 namespace sofa
00043 {
00044 
00045 namespace component
00046 {
00047 
00048 namespace topology
00049 {
00050 
00051     using namespace std;
00052     using namespace sofa::defaulttype;
00053 
00054   SOFA_DECL_CLASS(ManifoldEdgeSetTopologyContainer)
00055   int ManifoldEdgeSetTopologyContainerClass = core::RegisterObject("ManifoldEdge set topology container")
00056     .add< ManifoldEdgeSetTopologyContainer >()
00057     ;
00058 
00059     ManifoldEdgeSetTopologyContainer::ManifoldEdgeSetTopologyContainer()                                                                            
00060     : EdgeSetTopologyContainer( )
00061     {}
00062 
00063     ManifoldEdgeSetTopologyContainer::ManifoldEdgeSetTopologyContainer(const sofa::helper::vector< Edge > &edges )
00064     : EdgeSetTopologyContainer( edges )
00065     {}
00066 
00067     void ManifoldEdgeSetTopologyContainer::init()
00068     {
00069         // load edges
00070         EdgeSetTopologyContainer::init();
00071         
00072         // the edgeVertexShell is needed to recognize if the edgeSet is manifold
00073         createEdgeVertexShellArray();
00074 
00075         computeConnectedComponent();        
00076         checkTopology();
00077     }
00078 
00079     void ManifoldEdgeSetTopologyContainer::createEdgeVertexShellArray()
00080     {
00081         if(!hasEdges()) //  this method should only be called when edges exist
00082         {
00083     #ifndef NDEBUG
00084             cout << "Warning. [ManifoldEdgeSetTopologyContainer::createEdgeVertexShellArray] edge array is empty." << endl;
00085     #endif
00086             createEdgeSetArray();
00087         }
00088 
00089         if(hasEdgeVertexShell())
00090         {
00091             clearEdgeVertexShell();
00092         }
00093 
00094         m_edgeVertexShell.resize( getNbPoints() );
00095 
00096         for (unsigned int edge = 0; edge < m_edge.size(); ++edge)
00097         {
00098             // check to how many edges is the end vertex of each edge connnected to
00099             unsigned int size1 = m_edgeVertexShell[ m_edge[edge][1] ].size();
00100 
00101             // adding edge i in the edge shell of both points, while respecting the manifold orientation 
00102             // (ie : the edge will be added in second position for its first extremity point, and in first position for its second extremity point)
00103 
00104             m_edgeVertexShell[ m_edge[edge][0] ].push_back( edge ); 
00105 
00106             if(size1==0)
00107             {
00108                 m_edgeVertexShell[ m_edge[edge][1] ].push_back( edge );
00109             }
00110             else if(size1==1)
00111             {
00112                 unsigned int nextEdge = m_edgeVertexShell[ m_edge[edge][1] ][0];
00113                 m_edgeVertexShell[ m_edge[edge][1] ][0] = edge;
00114                 m_edgeVertexShell[ m_edge[edge][1] ].push_back( nextEdge );             
00115             }
00116             else
00117             {   // not manifold !!!
00118                 m_edgeVertexShell[ m_edge[edge][1] ].push_back( edge );
00119                 
00120                 std::cout << "Error. [ManifoldEdgeSetTopologyContainer::createEdgeVertexShellArray] The given EdgeSet is not manifold." << endl;
00121             }                       
00122         }
00123     }
00124 
00125     // Return the number of connected components
00126     int ManifoldEdgeSetTopologyContainer::getNumberConnectedComponents(sofa::helper::vector<unsigned int>& components) // const
00127     {
00128         computeConnectedComponent();
00129 
00130         components = m_ComponentVertexArray;
00131         return m_ConnectedComponentArray.size();
00132     }
00133 
00134     void ManifoldEdgeSetTopologyContainer::computeConnectedComponent()
00135     {
00136         using namespace boost;
00137         typedef adjacency_list <vecS, vecS, undirectedS> Graph;
00138 
00139         if(isvoid_ConnectedComponent()){
00140 
00141             Graph G;
00142 
00143             const sofa::helper::vector<Edge> &ea=getEdgeArray();
00144             for (unsigned int k=0;k<ea.size();++k) {
00145               add_edge(ea[k][0], ea[k][1], G);
00146             }
00147             
00148             m_ComponentVertexArray.resize(num_vertices(G));
00149             int num = connected_components(G, &m_ComponentVertexArray[0]);
00150 
00151             std::vector< std::vector<int> > components(num);
00152             for(int i=0;i<num;i++){
00153                 components[i].resize(4);
00154                 components[i][0]=0;
00155                 components[i][1]=-1;
00156                 components[i][2]=-1;
00157                 components[i][3]=-1;
00158             }
00159 
00160             for(unsigned int j=0;j<m_ComponentVertexArray.size();j++){
00161 
00162                 components[m_ComponentVertexArray[j]][0]+=1;
00163                 components[m_ComponentVertexArray[j]][1]=j;
00164 
00165                 if((getEdgeVertexShell(j)).size()==1){
00166 
00167                     if((getEdge((getEdgeVertexShell(j))[0]))[0]==j){
00168                         components[m_ComponentVertexArray[j]][2]=j;
00169                     }else{ // (getEdge((getEdgeVertexShell(j))[0]))[1]==j
00170                         components[m_ComponentVertexArray[j]][3]=j;
00171                     }   
00172                 }
00173             }
00174 
00175             for(int i=0;i<num;i++){
00176 
00177                 bool is_closed = (components[i][2]==-1 && components[i][3]==-1);
00178                 if(is_closed){
00179                     components[i][2]=components[i][1];
00180                 }
00181                 ConnectedComponent cc= ConnectedComponent(components[i][2], components[i][3], components[i][0], i);
00182                 m_ConnectedComponentArray.push_back(cc);
00183             }           
00184         
00185         }else{
00186             return;
00187         }
00188     }
00189 
00190     bool ManifoldEdgeSetTopologyContainer::checkTopology() const
00191     {
00192     #ifndef NDEBUG
00193         bool ret = true;
00194 
00195         if (hasEdgeVertexShell()) 
00196         {
00197             for (unsigned int i=0; i<m_edgeVertexShell.size(); ++i) 
00198             {
00199                 const sofa::helper::vector<unsigned int> &es = m_edgeVertexShell[i];                        
00200 
00201                 if(es.size() != 1 && es.size() != 2)
00202                 {
00203                     //std::cerr << "ERROR: ManifoldEdgeSetTopologyContainer::checkTopology() fails .\n";
00204                     std::cout << "*** CHECK FAILED : check_manifold_edge_vertex_shell, i = " << i << std::endl;
00205                     ret = false;
00206                 }
00207             }       
00208         }
00209 
00210         return ret &&  EdgeSetTopologyContainer::checkTopology();
00211     #else
00212         return true;
00213     #endif
00214     }
00215 
00216     void ManifoldEdgeSetTopologyContainer::clear()
00217     {
00218         m_ComponentVertexArray.clear();
00219         m_ConnectedComponentArray.clear();
00220 
00221         EdgeSetTopologyContainer::clear();
00222     }
00223 
00224 } // namespace topology
00225 
00226 } // namespace component
00227 
00228 } // namespace sofa
00229 

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