QuadSetTopologyContainer.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/QuadSetTopologyContainer.h>
00027 
00028 #include <sofa/core/ObjectFactory.h>
00029 
00030 #include <sofa/component/MeshLoader.h>
00031 
00032 namespace sofa
00033 {
00034 namespace component
00035 {
00036 namespace topology
00037 {
00038     using namespace std;
00039     using namespace sofa::defaulttype;
00040 
00041   SOFA_DECL_CLASS(QuadSetTopologyContainer)
00042   int QuadSetTopologyContainerClass = core::RegisterObject("Quad set topology container")
00043     .add< QuadSetTopologyContainer >()
00044     ;
00045 
00046     QuadSetTopologyContainer::QuadSetTopologyContainer()
00047     : EdgeSetTopologyContainer()
00048     {}
00049 
00050 QuadSetTopologyContainer::QuadSetTopologyContainer(const sofa::helper::vector< Quad >& quads )
00051 : EdgeSetTopologyContainer()
00052 , m_quad( quads )
00053 {
00054     for (unsigned int i=0; i<m_quad.size(); ++i)
00055     {
00056         for(unsigned int j=0; j<4; ++j)
00057         {
00058             int a = m_quad[i][j];
00059             if (a >= (int)nbPoints) nbPoints = a+1;
00060         }
00061     }
00062 }
00063 
00064 void QuadSetTopologyContainer::addQuad( int a, int b, int c, int d )
00065 {
00066     m_quad.push_back(Quad(a,b,c,d));
00067     if (a >= (int)nbPoints) nbPoints = a+1;
00068     if (b >= (int)nbPoints) nbPoints = b+1;
00069     if (c >= (int)nbPoints) nbPoints = c+1;
00070     if (d >= (int)nbPoints) nbPoints = d+1;
00071 }
00072 
00073     void QuadSetTopologyContainer::init()
00074     {
00075         EdgeSetTopologyContainer::init();
00076     }
00077 
00078     void QuadSetTopologyContainer::loadFromMeshLoader(sofa::component::MeshLoader* loader)
00079     {
00080         // load points
00081         PointSetTopologyContainer::loadFromMeshLoader(loader);
00082         m_quad = loader->getQuads();
00083     }
00084 
00085     void QuadSetTopologyContainer::createQuadSetArray()
00086     {
00087     #ifndef NDEBUG
00088         cout << "Error. [QuadSetTopologyContainer::createQuadSetArray] This method must be implemented by a child topology." << endl;
00089     #endif
00090     }
00091 
00092     void QuadSetTopologyContainer::createQuadVertexShellArray()
00093     {
00094         if(!hasQuads()) // this method should only be called when quads exist
00095         {
00096     #ifndef NDEBUG
00097             cout << "Warning. [QuadSetTopologyContainer::createQuadVertexShellArray] quad array is empty." << endl;
00098     #endif
00099             createQuadSetArray();
00100         }
00101 
00102         if(hasQuadVertexShell())
00103         {
00104             clearQuadVertexShell();
00105         }
00106 
00107         m_quadVertexShell.resize( getNbPoints() );
00108 
00109         for (unsigned int i=0; i<m_quad.size(); ++i)
00110         {
00111             // adding quad i in the quad shell of all points
00112             for (unsigned int j=0; j<4; ++j) 
00113             {
00114                 m_quadVertexShell[ m_quad[i][j] ].push_back( i );
00115             }
00116         }
00117     }
00118 
00119     void QuadSetTopologyContainer::createQuadEdgeShellArray()
00120     {
00121         if(!hasQuads()) // this method should only be called when quads exist
00122         {
00123     #ifndef NDEBUG
00124             cout << "Warning. [QuadSetTopologyContainer::createQuadEdgeShellArray] quad array is empty." << endl;
00125     #endif
00126             createQuadSetArray();
00127         }
00128 
00129         if(!hasEdges()) // this method should only be called when edges exist
00130         {
00131     #ifndef NDEBUG
00132             cout << "Warning. [QuadSetTopologyContainer::createQuadEdgeShellArray] edge array is empty." << endl;
00133     #endif
00134             createEdgeSetArray();
00135         }
00136 
00137         if(!hasQuadEdges())
00138             createQuadEdgeArray();
00139 
00140         const unsigned int numQuads = getNumberOfQuads();
00141         const unsigned int numEdges = getNumberOfEdges();
00142 
00143         if(hasQuadEdgeShell())
00144         {
00145             clearQuadEdgeShell();
00146         }
00147 
00148         m_quadEdgeShell.resize(numEdges);
00149 
00150         for (unsigned int i=0; i<numQuads; ++i)
00151         {
00152             // adding quad i in the quad shell of all edges
00153             for (unsigned int j=0; j<4; ++j) 
00154             { 
00155                 m_quadEdgeShell[ m_quadEdge[i][j] ].push_back( i );
00156             }
00157         }
00158     }
00159 
00160     void QuadSetTopologyContainer::createEdgeSetArray()
00161     {
00162         if(!hasQuads()) // this method should only be called when quads exist
00163         {
00164     #ifndef NDEBUG
00165             cout << "Warning. [QuadSetTopologyContainer::createEdgeSetArray] quad array is empty." << endl;
00166     #endif
00167             createQuadSetArray();
00168         }
00169 
00170         if(hasEdges()) 
00171         {
00172         #ifndef NDEBUG
00173                 cout << "Warning. [QuadSetTopologyContainer::createEdgeSetArray] edge array is not empty." << endl;
00174         #endif
00175 
00176             // clear edges and all shells that depend on edges
00177             EdgeSetTopologyContainer::clear();
00178 
00179             if(hasQuadEdges())
00180                 clearQuadEdges();
00181 
00182             if(hasQuadEdgeShell())
00183                 clearQuadEdgeShell();
00184         }
00185 
00186         // create a temporary map to find redundant edges
00187         std::map<Edge, unsigned int> edgeMap;
00188 
00189         for (unsigned int i=0; i<m_quad.size(); ++i)
00190         {
00191             const Quad &t = m_quad[i];
00192             for(unsigned int j=0; j<4; ++j)
00193             { 
00194                 const unsigned int v1 = t[(j+1)%4];
00195                 const unsigned int v2 = t[(j+2)%4];
00196 
00197                 // sort vertices in lexicographic order
00198                 const Edge e = ((v1<v2) ? Edge(v1,v2) : Edge(v2,v1));
00199 
00200                 if(edgeMap.find(e) == edgeMap.end()) 
00201                 {
00202                 // edge not in edgeMap so create a new one
00203                     const int edgeIndex = edgeMap.size();
00204                     edgeMap[e] = edgeIndex;
00205                     m_edge.push_back(e);
00206                 } 
00207             }
00208         }
00209     }
00210 
00211     void QuadSetTopologyContainer::createQuadEdgeArray()
00212     {
00213         if(!hasQuads()) // this method should only be called when quads exist
00214         {
00215     #ifndef NDEBUG
00216             cout << "Warning. [QuadSetTopologyContainer::createQuadEdgeArray] quad array is empty." << endl;
00217     #endif
00218             createQuadSetArray();
00219         }
00220 
00221         if(!hasEdges()) // this method should only be called when edges exist
00222         {
00223     #ifndef NDEBUG
00224             cout << "Warning. [QuadSetTopologyContainer::createQuadEdgeArray] edge array is empty." << endl;
00225     #endif
00226             createEdgeSetArray();
00227         }
00228 
00229         if(hasQuadEdges())
00230             clearQuadEdges();
00231 
00232         const unsigned int numQuads = getNumberOfQuads();
00233 
00234         m_quadEdge.resize( numQuads );
00235 
00236         for(unsigned int i=0; i<numQuads; ++i)
00237         {
00238             Quad &t = m_quad[i];
00239             // adding edge i in the edge shell of both points
00240             for (unsigned int j=0; j<4; ++j) 
00241             { 
00242                 const int edgeIndex = getEdgeIndex(t[(j+1)%4],t[(j+2)%4]);
00243                 m_quadEdge[i][j]=edgeIndex; 
00244             }
00245         }
00246     }
00247 
00248     const sofa::helper::vector<Quad> &QuadSetTopologyContainer::getQuadArray()
00249     {
00250         if(!hasQuads() && getNbPoints()>0)
00251         {
00252     #ifndef NDEBUG
00253             cout << "Warning. [QuadSetTopologyContainer::getQuadArray] creating quad array." << endl;
00254     #endif
00255             createQuadSetArray();
00256         }
00257 
00258         return m_quad;
00259     }
00260 
00261     int QuadSetTopologyContainer::getQuadIndex(PointID v1, PointID v2, PointID v3, PointID v4)
00262     {
00263         if(!hasQuadVertexShell())
00264             createQuadVertexShellArray();
00265 
00266         sofa::helper::vector<unsigned int> set1 = getQuadVertexShell(v1);
00267         sofa::helper::vector<unsigned int> set2 = getQuadVertexShell(v2);
00268         sofa::helper::vector<unsigned int> set3 = getQuadVertexShell(v3);
00269         sofa::helper::vector<unsigned int> set4 = getQuadVertexShell(v4);
00270 
00271         sort(set1.begin(), set1.end());
00272         sort(set2.begin(), set2.end());
00273         sort(set3.begin(), set3.end());
00274         sort(set4.begin(), set4.end());
00275 
00276         // The destination vector must be large enough to contain the result.
00277         sofa::helper::vector<unsigned int> out1(set1.size()+set2.size());
00278         sofa::helper::vector<unsigned int>::iterator result1;
00279         result1 = std::set_intersection(set1.begin(),set1.end(),set2.begin(),set2.end(),out1.begin());
00280         out1.erase(result1,out1.end());
00281 
00282         sofa::helper::vector<unsigned int> out2(set3.size()+out1.size());
00283         sofa::helper::vector<unsigned int>::iterator result2;
00284         result2 = std::set_intersection(set3.begin(),set3.end(),out1.begin(),out1.end(),out2.begin());
00285         out2.erase(result2,out2.end());
00286 
00287         sofa::helper::vector<unsigned int> out3(set4.size()+out2.size());
00288         sofa::helper::vector<unsigned int>::iterator result3;
00289         result3 = std::set_intersection(set4.begin(),set4.end(),out2.begin(),out2.end(),out3.begin());
00290         out3.erase(result3,out3.end());
00291 
00292     #ifndef NDEBUG
00293         if(out3.size() > 1)
00294             cout << "Warning. [QuadSetTopologyContainer::getQuadIndex] more than one quad found" << endl;
00295     #endif
00296 
00297         if(out3.size()==1)
00298             return (int) (out3[0]);
00299         else
00300             return -1;
00301     }
00302 
00303     unsigned int QuadSetTopologyContainer::getNumberOfQuads() const
00304     {
00305         return m_quad.size();
00306     }
00307 
00308     const sofa::helper::vector< sofa::helper::vector<unsigned int> > &QuadSetTopologyContainer::getQuadVertexShellArray() 
00309     {
00310         if(!hasQuadVertexShell())   // this method should only be called when the shell array exists
00311         {
00312     #ifndef NDEBUG
00313             cout << "Warning. [QuadSetTopologyContainer::getQuadVertexShellArray] quad vertex shell array is empty." << endl;
00314     #endif
00315             createQuadVertexShellArray();
00316         }
00317 
00318         return m_quadVertexShell;
00319     }
00320 
00321     const sofa::helper::vector< sofa::helper::vector<unsigned int> > &QuadSetTopologyContainer::getQuadEdgeShellArray() 
00322     {
00323         if(!hasQuadEdgeShell()) // this method should only be called when the shell array exists
00324         {
00325     #ifndef NDEBUG
00326             cout << "Warning. [QuadSetTopologyContainer::getQuadEdgeShellArray] quad edge shell array is empty." << endl;
00327     #endif
00328             createQuadEdgeShellArray();
00329         }
00330 
00331         return m_quadEdgeShell;
00332     }
00333 
00334     const sofa::helper::vector< QuadEdges> &QuadSetTopologyContainer::getQuadEdgeArray() 
00335     {
00336         if(m_quadEdge.empty())
00337             createQuadEdgeArray();
00338 
00339         return m_quadEdge;
00340     }
00341 
00342     const VertexQuads& QuadSetTopologyContainer::getQuadVertexShell(PointID i)
00343     {
00344         if(!hasQuadVertexShell())   // this method should only be called when the shell array exists
00345         {
00346     #ifndef NDEBUG
00347             cout << "Warning. [QuadSetTopologyContainer::getQuadVertexShell] quad vertex shell array is empty." << endl;
00348     #endif
00349             createQuadVertexShellArray();
00350         }
00351         else if( i >= m_quadVertexShell.size())
00352         {
00353     #ifndef NDEBUG
00354             cout << "Error. [QuadSetTopologyContainer::getQuadVertexShell] index out of bounds." << endl;
00355     #endif
00356             createQuadVertexShellArray();
00357         }
00358 
00359         return m_quadVertexShell[i];
00360     }
00361 
00362     const EdgeQuads& QuadSetTopologyContainer::getQuadEdgeShell(EdgeID i)
00363     {
00364         if(!hasQuadEdgeShell()) // this method should only be called when the shell array exists
00365         {
00366     #ifndef NDEBUG
00367             cout << "Warning. [QuadSetTopologyContainer::getQuadEdgeShell] quad edge shell array is empty." << endl;
00368     #endif
00369             createQuadEdgeShellArray();
00370         }
00371         else if( i >= m_quadEdgeShell.size())
00372         {
00373     #ifndef NDEBUG
00374             cout << "Error. [QuadSetTopologyContainer::getQuadEdgeShell] index out of bounds." << endl;
00375     #endif
00376             createQuadEdgeShellArray();
00377         }
00378 
00379         return m_quadEdgeShell[i];
00380     }
00381 
00382     const QuadEdges &QuadSetTopologyContainer::getQuadEdge(const unsigned int i) 
00383     {
00384         if(m_quadEdge.empty())
00385             createQuadEdgeArray();
00386         
00387         if( i >= m_quadEdge.size())
00388         {
00389     #ifndef NDEBUG
00390             cout << "Error. [QuadSetTopologyContainer::getQuadEdge] index out of bounds." << endl;
00391     #endif
00392             createQuadEdgeArray();
00393         }
00394 
00395         return m_quadEdge[i];
00396     }
00397 
00398     int QuadSetTopologyContainer::getVertexIndexInQuad(Quad &t, unsigned int vertexIndex) const
00399     {
00400         if(t[0]==vertexIndex)
00401             return 0;
00402         else if(t[1]==vertexIndex)
00403             return 1;
00404         else if(t[2]==vertexIndex)
00405             return 2;
00406         else if(t[3]==vertexIndex)
00407             return 3;
00408         else 
00409             return -1;
00410     }
00411 
00412     int QuadSetTopologyContainer::getEdgeIndexInQuad(QuadEdges &t, unsigned int edgeIndex) const
00413     {
00414         if(t[0]==edgeIndex)
00415             return 0;
00416         else if(t[1]==edgeIndex)
00417             return 1;
00418         else if(t[2]==edgeIndex)
00419             return 2;
00420         else if(t[3]==edgeIndex)
00421             return 3;
00422         else 
00423             return -1;
00424     }
00425 
00426     sofa::helper::vector< unsigned int > &QuadSetTopologyContainer::getQuadEdgeShellForModification(const unsigned int i) 
00427     {
00428         if(!hasQuadEdgeShell()) // this method should only be called when the shell array exists
00429         {
00430     #ifndef NDEBUG
00431             cout << "Warning. [QuadSetTopologyContainer::getQuadEdgeShellForModification] quad edge shell array is empty." << endl;
00432     #endif
00433             createQuadEdgeShellArray();
00434         }
00435         
00436         if( i >= m_quadEdgeShell.size())
00437         {
00438     #ifndef NDEBUG
00439             cout << "Error. [QuadSetTopologyContainer::getQuadEdgeShellForModification] index out of bounds." << endl;
00440     #endif
00441             createQuadEdgeShellArray();
00442         }
00443 
00444         return m_quadEdgeShell[i];
00445     }
00446 
00447     sofa::helper::vector< unsigned int > &QuadSetTopologyContainer::getQuadVertexShellForModification(const unsigned int i) 
00448     {
00449         if(!hasQuadVertexShell())   // this method should only be called when the shell array exists
00450         {
00451     #ifndef NDEBUG
00452             cout << "Warning. [QuadSetTopologyContainer::getQuadVertexShellForModification] quad vertex shell array is empty." << endl;
00453     #endif
00454             createQuadVertexShellArray();
00455         }
00456         
00457         if( i >= m_quadVertexShell.size())
00458         {
00459     #ifndef NDEBUG
00460             cout << "Error. [QuadSetTopologyContainer::getQuadVertexShellForModification] index out of bounds." << endl;
00461     #endif
00462             createQuadVertexShellArray();
00463         }
00464 
00465         return m_quadVertexShell[i];
00466     }
00467 
00468 
00469     bool QuadSetTopologyContainer::checkTopology() const
00470     {
00471     #ifndef NDEBUG
00472         bool ret = true;
00473 
00474         if(hasQuadVertexShell()) 
00475         {
00476             for (unsigned int i=0; i<m_quadVertexShell.size(); ++i) 
00477             {
00478                 const sofa::helper::vector<unsigned int> &tvs = m_quadVertexShell[i];
00479                 for (unsigned int j=0; j<tvs.size(); ++j)
00480                 {
00481                     if((m_quad[tvs[j]][0]!=i) 
00482                     && (m_quad[tvs[j]][1]!=i) 
00483                     && (m_quad[tvs[j]][2]!=i) 
00484                     && (m_quad[tvs[j]][3]!=i))
00485                     {
00486                         ret = false;
00487                         std::cout << "*** CHECK FAILED : check_quad_vertex_shell, i = " << i << " , j = " << j << std::endl;
00488                     }
00489                 }
00490             }
00491         }
00492 
00493         if(hasQuadEdgeShell()) 
00494         {
00495             for (unsigned int i=0; i<m_quadEdgeShell.size(); ++i) 
00496             {
00497                 const sofa::helper::vector<unsigned int> &tes = m_quadEdgeShell[i];
00498                 for (unsigned int j=0; j<tes.size(); ++j)
00499                 {
00500                     if((m_quadEdge[tes[j]][0]!=i) 
00501                     && (m_quadEdge[tes[j]][1]!=i) 
00502                     && (m_quadEdge[tes[j]][2]!=i) 
00503                     && (m_quadEdge[tes[j]][3]!=i))
00504                     {
00505                         ret = false;
00506                         std::cout << "*** CHECK FAILED : check_quad_edge_shell, i = " << i << " , j = " << j << std::endl;
00507                     }
00508                 }
00509             }
00510         }
00511 
00512         return ret && EdgeSetTopologyContainer::checkTopology();
00513     #else
00514         return true;
00515     #endif
00516     }
00517 
00518     bool QuadSetTopologyContainer::hasQuads() const 
00519     {
00520         return !m_quad.empty();
00521     }
00522 
00523     bool QuadSetTopologyContainer::hasQuadEdges() const 
00524     {
00525         return !m_quadEdge.empty();
00526     }
00527 
00528     bool QuadSetTopologyContainer::hasQuadVertexShell() const 
00529     {
00530         return !m_quadVertexShell.empty();
00531     }
00532 
00533     bool QuadSetTopologyContainer::hasQuadEdgeShell() const 
00534     {
00535         return !m_quadEdgeShell.empty();
00536     }
00537 
00538     void QuadSetTopologyContainer::clearQuadVertexShell()
00539     {
00540         for(unsigned int i=0; i<m_quadVertexShell.size(); ++i)
00541             m_quadVertexShell[i].clear();
00542 
00543         m_quadVertexShell.clear();
00544     }
00545 
00546     void QuadSetTopologyContainer::clearQuadEdgeShell()
00547     {
00548         for(unsigned int i=0; i<m_quadEdgeShell.size(); ++i)
00549             m_quadEdgeShell[i].clear();
00550 
00551         m_quadEdgeShell.clear();
00552     }
00553 
00554     void QuadSetTopologyContainer::clearQuadEdges()
00555     {
00556         m_quadEdge.clear();
00557     }
00558 
00559     void QuadSetTopologyContainer::clearQuads()
00560     {
00561         m_quad.clear();
00562     }
00563 
00564     void QuadSetTopologyContainer::clear()
00565     {
00566         clearQuadVertexShell();
00567         clearQuadEdgeShell();
00568         clearQuadEdges();
00569         clearQuads();
00570 
00571         EdgeSetTopologyContainer::clear();
00572     }
00573 
00574 } // namespace topology
00575 
00576 } // namespace component
00577 
00578 } // namespace sofa
00579 

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