00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/component/topology/TriangleSetTopologyModifier.h>
00026 #include <sofa/component/topology/TriangleSetTopologyChange.h>
00027 #include <sofa/component/topology/TriangleSetTopologyContainer.h>
00028 #include <algorithm>
00029 #include <functional>
00030 #include <iostream>
00031 #include <sofa/core/ObjectFactory.h>
00032
00033 namespace sofa
00034 {
00035
00036 namespace component
00037 {
00038
00039 namespace topology
00040 {
00041 SOFA_DECL_CLASS(TriangleSetTopologyModifier)
00042 int TriangleSetTopologyModifierClass = core::RegisterObject("Triangle set topology modifier")
00043 .add< TriangleSetTopologyModifier >()
00044 ;
00045
00046 using namespace std;
00047 using namespace sofa::defaulttype;
00048
00049
00050 void TriangleSetTopologyModifier::init()
00051 {
00052 EdgeSetTopologyModifier::init();
00053 this->getContext()->get(m_container);
00054 }
00055
00056
00057 void TriangleSetTopologyModifier::addTriangleProcess(Triangle t)
00058 {
00059 #ifndef NDEBUG
00060
00061 if((t[0]==t[1]) || (t[0]==t[2]) || (t[1]==t[2]) )
00062 {
00063 cout << "Error: [TriangleSetTopologyModifier::addTriangle] : invalid quad: "
00064 << t[0] << ", " << t[1] << ", " << t[2] << endl;
00065
00066 return;
00067 }
00068
00069
00070
00071 if(m_container->hasTriangleVertexShell())
00072 {
00073 if(m_container->getTriangleIndex(t[0],t[1],t[2]) != -1)
00074 {
00075 cout << "Error: [TriangleSetTopologyModifier::addTriangle] : Triangle "
00076 << t[0] << ", " << t[1] << ", " << t[2] << " already exists." << endl;
00077 return;
00078 }
00079 }
00080 #endif
00081
00082 const unsigned int triangleIndex = m_container->getNumberOfTriangles();
00083
00084 if(m_container->hasTriangleVertexShell())
00085 {
00086 for(unsigned int j=0; j<3; ++j)
00087 {
00088 sofa::helper::vector< unsigned int > &shell = m_container->getTriangleVertexShellForModification( t[j] );
00089 shell.push_back( triangleIndex );
00090 }
00091 }
00092
00093 if(m_container->hasEdges())
00094 {
00095 for(unsigned int j=0; j<3; ++j)
00096 {
00097 int edgeIndex = m_container->getEdgeIndex(t[(j+1)%3], t[(j+2)%3]);
00098
00099 if(edgeIndex == -1)
00100 {
00101
00102 sofa::helper::vector< Edge > v(1);
00103 Edge e1 (t[(j+1)%3], t[(j+2)%3]);
00104 v[0] = e1;
00105
00106 addEdgesProcess((const sofa::helper::vector< Edge > &) v);
00107
00108 edgeIndex = m_container->getEdgeIndex(t[(j+1)%3],t[(j+2)%3]);
00109 sofa::helper::vector< unsigned int > edgeIndexList;
00110 edgeIndexList.push_back((unsigned int) edgeIndex);
00111 addEdgesWarning( v.size(), v, edgeIndexList);
00112 }
00113
00114 if(m_container->hasTriangleEdges())
00115 {
00116 m_container->m_triangleEdge.resize(triangleIndex+1);
00117 m_container->m_triangleEdge[triangleIndex][j]= edgeIndex;
00118 }
00119
00120 if(m_container->hasTriangleEdgeShell())
00121 {
00122 sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[m_container->m_triangleEdge[triangleIndex][j]];
00123 shell.push_back( triangleIndex );
00124 }
00125 }
00126 }
00127
00128 m_container->m_triangle.push_back(t);
00129 }
00130
00131
00132 void TriangleSetTopologyModifier::addTrianglesProcess(const sofa::helper::vector< Triangle > &triangles)
00133 {
00134 m_container->m_triangle.reserve(m_container->m_triangle.size() + triangles.size());
00135
00136 for(unsigned int i=0; i<triangles.size(); ++i)
00137 {
00138 addTriangleProcess(triangles[i]);
00139 }
00140 }
00141
00142
00143 void TriangleSetTopologyModifier::addTrianglesWarning(const unsigned int nTriangles,
00144 const sofa::helper::vector< Triangle >& trianglesList,
00145 const sofa::helper::vector< unsigned int >& trianglesIndexList)
00146 {
00147
00148 TrianglesAdded *e = new TrianglesAdded(nTriangles, trianglesList, trianglesIndexList);
00149 addTopologyChange(e);
00150 }
00151
00152
00153 void TriangleSetTopologyModifier::addTrianglesWarning(const unsigned int nTriangles,
00154 const sofa::helper::vector< Triangle >& trianglesList,
00155 const sofa::helper::vector< unsigned int >& trianglesIndexList,
00156 const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00157 const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs)
00158 {
00159
00160 TrianglesAdded *e=new TrianglesAdded(nTriangles, trianglesList,trianglesIndexList,ancestors,baryCoefs);
00161 addTopologyChange(e);
00162 }
00163
00164
00165 void TriangleSetTopologyModifier::removeTrianglesWarning( sofa::helper::vector<unsigned int> &triangles)
00166 {
00168 std::sort( triangles.begin(), triangles.end(), std::greater<unsigned int>() );
00169
00170
00171 TrianglesRemoved *e=new TrianglesRemoved(triangles);
00172 addTopologyChange(e);
00173 }
00174
00175
00176 void TriangleSetTopologyModifier::removeTrianglesProcess(const sofa::helper::vector<unsigned int> &indices,
00177 const bool removeIsolatedEdges,
00178 const bool removeIsolatedPoints)
00179 {
00180 if(!m_container->hasTriangles())
00181 {
00182 #ifndef NDEBUG
00183 cout << "Error. [TriangleSetTopologyModifier::removeTrianglesProcess] triangle array is empty." << endl;
00184 #endif
00185 return;
00186 }
00187
00188 if(m_container->hasEdges() && removeIsolatedEdges)
00189 {
00190 if(!m_container->hasTriangleEdges())
00191 m_container->createTriangleEdgeArray();
00192
00193 if(!m_container->hasTriangleEdgeShell())
00194 m_container->createTriangleEdgeShellArray();
00195 }
00196
00197 if(removeIsolatedPoints)
00198 {
00199 if(!m_container->hasTriangleVertexShell())
00200 m_container->createTriangleVertexShellArray();
00201 }
00202
00203 sofa::helper::vector<unsigned int> edgeToBeRemoved;
00204 sofa::helper::vector<unsigned int> vertexToBeRemoved;
00205
00206 unsigned int lastTriangle = m_container->getNumberOfTriangles() - 1;
00207 for(unsigned int i = 0; i<indices.size(); ++i, --lastTriangle)
00208 {
00209 Triangle &t = m_container->m_triangle[ indices[i] ];
00210 Triangle &q = m_container->m_triangle[ lastTriangle ];
00211
00212 if(m_container->hasTriangleVertexShell())
00213 {
00214 for(unsigned int j=0; j<3; ++j)
00215 {
00216 sofa::helper::vector< unsigned int > &shell = m_container->m_triangleVertexShell[ t[j] ];
00217 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00218 if(removeIsolatedPoints && shell.empty())
00219 vertexToBeRemoved.push_back(t[j]);
00220 }
00221 }
00222
00223 if(m_container->hasTriangleEdgeShell())
00224 {
00225 for(unsigned int j=0; j<3; ++j)
00226 {
00227 sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[ m_container->m_triangleEdge[indices[i]][j]];
00228 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00229 if(removeIsolatedEdges && shell.empty())
00230 edgeToBeRemoved.push_back(m_container->m_triangleEdge[indices[i]][j]);
00231 }
00232 }
00233
00234 if(indices[i] < lastTriangle)
00235 {
00236 if(m_container->hasTriangleVertexShell())
00237 {
00238 for(unsigned int j=0; j<3; ++j)
00239 {
00240 sofa::helper::vector< unsigned int > &shell = m_container->m_triangleVertexShell[ q[j] ];
00241 replace(shell.begin(), shell.end(), lastTriangle, indices[i]);
00242 }
00243 }
00244
00245 if(m_container->hasTriangleEdgeShell())
00246 {
00247 for(unsigned int j=0; j<3; ++j)
00248 {
00249 sofa::helper::vector< unsigned int > &shell = m_container->m_triangleEdgeShell[ m_container->m_triangleEdge[lastTriangle][j]];
00250 replace(shell.begin(), shell.end(), lastTriangle, indices[i]);
00251 }
00252 }
00253 }
00254
00255
00256 if(m_container->hasTriangleEdges())
00257 {
00258 m_container->m_triangleEdge[ indices[i] ] = m_container->m_triangleEdge[ lastTriangle ];
00259 m_container->m_triangleEdge.resize( lastTriangle );
00260 }
00261
00262
00263 m_container->m_triangle[ indices[i] ] = m_container->m_triangle[ lastTriangle ];
00264 m_container->m_triangle.resize( lastTriangle );
00265 }
00266
00267 if(!edgeToBeRemoved.empty())
00268 {
00270 removeEdgesWarning(edgeToBeRemoved);
00271 propagateTopologicalChanges();
00273 removeEdgesProcess(edgeToBeRemoved, false);
00274 }
00275
00276 if(!vertexToBeRemoved.empty())
00277 {
00278 removePointsWarning(vertexToBeRemoved);
00280 propagateTopologicalChanges();
00281 removePointsProcess(vertexToBeRemoved);
00282 }
00283 }
00284
00285 void TriangleSetTopologyModifier::addPointsProcess(const unsigned int nPoints)
00286 {
00287
00288 EdgeSetTopologyModifier::addPointsProcess( nPoints );
00289
00290
00291 if(m_container->hasTriangleVertexShell())
00292 m_container->m_triangleVertexShell.resize( m_container->getNbPoints() );
00293 }
00294
00295 void TriangleSetTopologyModifier::addEdgesProcess(const sofa::helper::vector< Edge > &edges)
00296 {
00297 if(!m_container->hasEdges())
00298 {
00299 m_container->createEdgeSetArray();
00300 }
00301
00302
00303 EdgeSetTopologyModifier::addEdgesProcess( edges );
00304
00305 if(m_container->hasTriangleEdgeShell())
00306 m_container->m_triangleEdgeShell.resize( m_container->m_triangleEdgeShell.size() + edges.size() );
00307 }
00308
00309 void TriangleSetTopologyModifier::removePointsProcess( sofa::helper::vector<unsigned int> &indices,
00310 const bool removeDOF)
00311 {
00312 if(m_container->hasTriangles())
00313 {
00314 if(!m_container->hasTriangleVertexShell())
00315 m_container->createTriangleVertexShellArray();
00316
00317 unsigned int lastPoint = m_container->getNbPoints() - 1;
00318 for(unsigned int i=0; i<indices.size(); ++i, --lastPoint)
00319 {
00320
00321
00322
00323 sofa::helper::vector<unsigned int> &shell = m_container->m_triangleVertexShell[lastPoint];
00324 for(unsigned int j=0; j<shell.size(); ++j)
00325 {
00326 const unsigned int q = shell[j];
00327 for(unsigned int k=0; k<3; ++k)
00328 {
00329 if(m_container->m_triangle[q][k] == lastPoint)
00330 m_container->m_triangle[q][k] = indices[i];
00331 }
00332 }
00333
00334
00335 m_container->m_triangleVertexShell[ indices[i] ] = m_container->m_triangleVertexShell[ lastPoint ];
00336 }
00337
00338 m_container->m_triangleVertexShell.resize( m_container->m_triangleVertexShell.size() - indices.size() );
00339 }
00340
00341
00342
00343 EdgeSetTopologyModifier::removePointsProcess( indices, removeDOF );
00344 }
00345
00346 void TriangleSetTopologyModifier::removeEdgesProcess( const sofa::helper::vector<unsigned int> &indices,
00347 const bool removeIsolatedItems)
00348 {
00349
00350
00351 if(m_container->hasTriangleEdges())
00352 {
00353 if(!m_container->hasTriangleEdgeShell())
00354 m_container->createTriangleEdgeShellArray();
00355
00356 unsigned int lastEdge = m_container->getNumberOfEdges() - 1;
00357 for(unsigned int i = 0; i < indices.size(); ++i, --lastEdge)
00358 {
00359
00360
00361 for(sofa::helper::vector<unsigned int>::iterator itt = m_container->m_triangleEdgeShell[lastEdge].begin();
00362 itt != m_container->m_triangleEdgeShell[lastEdge].end(); ++itt)
00363 {
00364 unsigned int edgeIndex = m_container->getEdgeIndexInTriangle(m_container->m_triangleEdge[(*itt)], lastEdge);
00365 m_container->m_triangleEdge[(*itt)][edgeIndex] = indices[i];
00366 }
00367
00368
00369 m_container->m_triangleEdgeShell[ indices[i] ] = m_container->m_triangleEdgeShell[ lastEdge ];
00370 }
00371
00372 m_container->m_triangleEdgeShell.resize( m_container->m_triangleEdgeShell.size() - indices.size() );
00373 }
00374
00375
00376 EdgeSetTopologyModifier::removeEdgesProcess(indices, removeIsolatedItems);
00377 }
00378
00379 void TriangleSetTopologyModifier::renumberPointsProcess( const sofa::helper::vector<unsigned int> &index,
00380 const sofa::helper::vector<unsigned int> &inv_index,
00381 const bool renumberDOF)
00382 {
00383 if(m_container->hasTriangles())
00384 {
00385 if(m_container->hasTriangleVertexShell())
00386 {
00387 sofa::helper::vector< sofa::helper::vector< unsigned int > > triangleVertexShell_cp = m_container->m_triangleVertexShell;
00388 for(unsigned int i=0; i<index.size(); ++i)
00389 {
00390 m_container->m_triangleVertexShell[i] = triangleVertexShell_cp[ index[i] ];
00391 }
00392 }
00393
00394 for(unsigned int i=0; i<m_container->m_triangle.size(); ++i)
00395 {
00396 m_container->m_triangle[i][0] = inv_index[ m_container->m_triangle[i][0] ];
00397 m_container->m_triangle[i][1] = inv_index[ m_container->m_triangle[i][1] ];
00398 m_container->m_triangle[i][2] = inv_index[ m_container->m_triangle[i][2] ];
00399 }
00400 }
00401
00402
00403 EdgeSetTopologyModifier::renumberPointsProcess( index, inv_index, renumberDOF );
00404 }
00405
00406 void TriangleSetTopologyModifier::removeTriangles(sofa::helper::vector< unsigned int >& triangles,
00407 const bool removeIsolatedEdges,
00408 const bool removeIsolatedPoints)
00409 {
00411 removeTrianglesWarning(triangles);
00412
00413 propagateTopologicalChanges();
00414
00415 removeTrianglesProcess( triangles ,removeIsolatedEdges, removeIsolatedPoints);
00416
00417 m_container->checkTopology();
00418 }
00419
00420 void TriangleSetTopologyModifier::removeItems(sofa::helper::vector< unsigned int >& items)
00421 {
00422 removeTriangles(items, true, true);
00423 }
00424
00425 void TriangleSetTopologyModifier::renumberPoints( const sofa::helper::vector<unsigned int> &index,
00426 const sofa::helper::vector<unsigned int> &inv_index)
00427 {
00429 renumberPointsWarning(index, inv_index);
00430
00431 propagateTopologicalChanges();
00432
00433 renumberPointsProcess(index, inv_index);
00434
00435 m_container->checkTopology();
00436 }
00437
00438
00439 }
00440
00441 }
00442
00443 }
00444