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
1.5.7.1