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/TetrahedronSetTopologyModifier.h>
00026 #include <sofa/component/topology/TetrahedronSetTopologyChange.h>
00027 #include <sofa/component/topology/TetrahedronSetTopologyContainer.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(TetrahedronSetTopologyModifier)
00042 int TetrahedronSetTopologyModifierClass = core::RegisterObject("Tetrahedron set topology modifier")
00043 .add< TetrahedronSetTopologyModifier >();
00044
00045 using namespace std;
00046 using namespace sofa::defaulttype;
00047 using namespace sofa::core::componentmodel::behavior;
00048
00049 const unsigned int tetrahedronEdgeArray[6][2] = {{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}};
00050
00051
00052 void TetrahedronSetTopologyModifier::init()
00053 {
00054 TriangleSetTopologyModifier::init();
00055
00056 this->getContext()->get(m_container);
00057 }
00058
00059
00060 void TetrahedronSetTopologyModifier::addTetrahedronProcess(Tetrahedron t)
00061 {
00062 #ifndef NDEBUG
00063
00064 assert(t[0]!=t[1]);
00065 assert(t[0]!=t[2]);
00066 assert(t[0]!=t[3]);
00067 assert(t[1]!=t[2]);
00068 assert(t[1]!=t[3]);
00069 assert(t[2]!=t[3]);
00070
00071
00072
00073 #endif
00074 const unsigned int tetrahedronIndex = m_container->m_tetrahedron.size();
00075
00076 if (m_container->hasTetrahedronTriangles())
00077 {
00078 for (unsigned int j=0; j<4; ++j)
00079 {
00080 int triangleIndex = m_container->getTriangleIndex(t[(j+1)%4], t[(j+2)%4], t[(j+3)%4]);
00081
00082 if(triangleIndex == -1)
00083 {
00084
00085 sofa::helper::vector< Triangle > v;
00086 Triangle e1 (t[(j+1)%4],t[(j+2)%4],t[(j+3)%4]);
00087 v.push_back(e1);
00088
00089 addTrianglesProcess((const sofa::helper::vector< Triangle > &) v);
00090
00091 triangleIndex = m_container->getTriangleIndex(t[(j+1)%4], t[(j+2)%4], t[(j+3)%4]);
00092
00093 sofa::helper::vector< unsigned int > triangleIndexList;
00094 triangleIndexList.push_back(triangleIndex);
00095 addTrianglesWarning( v.size(), v, triangleIndexList);
00096 }
00097
00098 m_container->m_tetrahedronTriangle.resize(triangleIndex+1);
00099 m_container->m_tetrahedronTriangle[tetrahedronIndex][j]= triangleIndex;
00100 }
00101 }
00102
00103 if (m_container->hasTetrahedronEdges())
00104 {
00105 for (unsigned int j=0; j<6; ++j)
00106 {
00107 int edgeIndex=m_container->getEdgeIndex(tetrahedronEdgeArray[j][0],
00108 tetrahedronEdgeArray[j][1]);
00109 assert(edgeIndex!= -1);
00110
00111 m_container->m_tetrahedronEdge.resize(edgeIndex+1);
00112 m_container->m_tetrahedronEdge[tetrahedronIndex][j]= edgeIndex;
00113 }
00114 }
00115
00116 if (m_container->hasTetrahedronVertexShell())
00117 {
00118 for (unsigned int j=0; j<4; ++j)
00119 {
00120 sofa::helper::vector< unsigned int > &shell = m_container->getTetrahedronVertexShellForModification( t[j] );
00121 shell.push_back( tetrahedronIndex );
00122 }
00123 }
00124
00125 if (m_container->hasTetrahedronEdgeShell())
00126 {
00127 for (unsigned int j=0; j<6; ++j)
00128 {
00129 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronEdgeShell[m_container->m_tetrahedronEdge[tetrahedronIndex][j]];
00130 shell.push_back( tetrahedronIndex );
00131 }
00132 }
00133
00134 if (m_container->hasTetrahedronTriangleShell())
00135 {
00136 for (unsigned int j=0; j<4; ++j)
00137 {
00138 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronTriangleShell[m_container->m_tetrahedronTriangle[tetrahedronIndex][j]];
00139 shell.push_back( tetrahedronIndex );
00140 }
00141 }
00142
00143 m_container->m_tetrahedron.push_back(t);
00144 }
00145
00146
00147 void TetrahedronSetTopologyModifier::addTetrahedraProcess(const sofa::helper::vector< Tetrahedron > &tetrahedra)
00148 {
00149 for (unsigned int i = 0; i < tetrahedra.size(); ++i)
00150 {
00151 addTetrahedronProcess(tetrahedra[i]);
00152 }
00153 }
00154
00155
00156 void TetrahedronSetTopologyModifier::addTetrahedraWarning(const unsigned int nTetrahedra,
00157 const sofa::helper::vector< Tetrahedron >& tetrahedraList,
00158 const sofa::helper::vector< unsigned int >& tetrahedraIndexList)
00159 {
00160
00161 TetrahedraAdded *e = new TetrahedraAdded(nTetrahedra, tetrahedraList, tetrahedraIndexList);
00162 addTopologyChange(e);
00163 }
00164
00165
00166 void TetrahedronSetTopologyModifier::addTetrahedraWarning(const unsigned int nTetrahedra,
00167 const sofa::helper::vector< Tetrahedron >& tetrahedraList,
00168 const sofa::helper::vector< unsigned int >& tetrahedraIndexList,
00169 const sofa::helper::vector< sofa::helper::vector< unsigned int > > & ancestors,
00170 const sofa::helper::vector< sofa::helper::vector< double > >& baryCoefs)
00171 {
00172
00173 TetrahedraAdded *e = new TetrahedraAdded(nTetrahedra, tetrahedraList, tetrahedraIndexList, ancestors, baryCoefs);
00174 addTopologyChange(e);
00175 }
00176
00177
00178 void TetrahedronSetTopologyModifier::removeTetrahedraWarning( sofa::helper::vector<unsigned int> &tetrahedra )
00179 {
00181 std::sort( tetrahedra.begin(), tetrahedra.end(), std::greater<unsigned int>() );
00182
00183
00184 TetrahedraRemoved *e=new TetrahedraRemoved(tetrahedra);
00185 addTopologyChange(e);
00186 }
00187
00188
00189 void TetrahedronSetTopologyModifier::removeTetrahedraProcess( const sofa::helper::vector<unsigned int> &indices,
00190 const bool removeIsolatedItems)
00191 {
00192 if(!m_container->hasTetrahedra())
00193 return;
00194
00195 bool removeIsolatedVertices = removeIsolatedItems;
00196 bool removeIsolatedEdges = removeIsolatedItems && m_container->hasEdges();
00197 bool removeIsolatedTriangles = removeIsolatedItems && m_container->hasTriangles();
00198
00199 if(removeIsolatedVertices)
00200 {
00201 if(!m_container->hasTetrahedronVertexShell())
00202 m_container->createTetrahedronVertexShellArray();
00203 }
00204
00205 if(removeIsolatedEdges)
00206 {
00207 if(!m_container->hasTetrahedronEdgeShell())
00208 m_container->createTetrahedronEdgeShellArray();
00209 }
00210
00211 if(removeIsolatedTriangles)
00212 {
00213 if(!m_container->hasTetrahedronTriangleShell())
00214 m_container->createTetrahedronTriangleShellArray();
00215 }
00216
00217 sofa::helper::vector<unsigned int> triangleToBeRemoved;
00218 sofa::helper::vector<unsigned int> edgeToBeRemoved;
00219 sofa::helper::vector<unsigned int> vertexToBeRemoved;
00220
00221 unsigned int lastTetrahedron = m_container->getNumberOfTetrahedra() - 1;
00222 for (unsigned int i=0; i<indices.size(); ++i, --lastTetrahedron)
00223 {
00224 Tetrahedron &t = m_container->m_tetrahedron[ indices[i] ];
00225 Tetrahedron &h = m_container->m_tetrahedron[ lastTetrahedron ];
00226
00227 if (m_container->hasTetrahedronVertexShell())
00228 {
00229 for(unsigned int j=0; j<4; ++j)
00230 {
00231 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronVertexShell[ t[j] ];
00232 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00233 if(removeIsolatedVertices && shell.empty())
00234 vertexToBeRemoved.push_back(t[j]);
00235 }
00236 }
00237
00238 if(m_container->hasTetrahedronEdgeShell())
00239 {
00240 for(unsigned int j=0; j<6; ++j)
00241 {
00242 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronEdgeShell[ m_container->m_tetrahedronEdge[indices[i]][j]];
00243 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00244 if(removeIsolatedEdges && shell.empty())
00245 edgeToBeRemoved.push_back(m_container->m_tetrahedronEdge[indices[i]][j]);
00246 }
00247 }
00248
00249 if(m_container->hasTetrahedronTriangleShell())
00250 {
00251 for(unsigned int j=0; j<4; ++j)
00252 {
00253 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronTriangleShell[ m_container->m_tetrahedronTriangle[indices[i]][j]];
00254 shell.erase(remove(shell.begin(), shell.end(), indices[i]), shell.end());
00255 if(removeIsolatedTriangles && shell.empty())
00256 triangleToBeRemoved.push_back(m_container->m_tetrahedronTriangle[indices[i]][j]);
00257 }
00258 }
00259
00260
00261 if ( indices[i] < lastTetrahedron )
00262 {
00263 if (m_container->hasTetrahedronVertexShell())
00264 {
00265 for(unsigned int j=0; j<4; ++j)
00266 {
00267 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronVertexShell[ h[j] ];
00268 replace(shell.begin(), shell.end(), lastTetrahedron, indices[i]);
00269 }
00270 }
00271
00272 if (m_container->hasTetrahedronEdgeShell())
00273 {
00274 for(unsigned int j=0; j<6; ++j)
00275 {
00276 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronEdgeShell[ m_container->m_tetrahedronEdge[lastTetrahedron][j]];
00277 replace(shell.begin(), shell.end(), lastTetrahedron, indices[i]);
00278 }
00279 }
00280
00281 if (m_container->hasTetrahedronTriangleShell())
00282 {
00283 for(unsigned int j=0; j<4; ++j)
00284 {
00285 sofa::helper::vector< unsigned int > &shell = m_container->m_tetrahedronTriangleShell[ m_container->m_tetrahedronTriangle[lastTetrahedron][j]];
00286 replace(shell.begin(), shell.end(), lastTetrahedron, indices[i]);
00287 }
00288 }
00289 }
00290
00291 if (m_container->hasTetrahedronTriangles())
00292 {
00293
00294 m_container->m_tetrahedronTriangle[ indices[i] ] = m_container->m_tetrahedronTriangle[ lastTetrahedron ];
00295 m_container->m_tetrahedronTriangle.resize( lastTetrahedron );
00296 }
00297
00298 if (m_container->hasTetrahedronEdges())
00299 {
00300
00301 m_container->m_tetrahedronEdge[ indices[i] ] = m_container->m_tetrahedronEdge[ lastTetrahedron ];
00302 m_container->m_tetrahedronEdge.resize( lastTetrahedron );
00303 }
00304
00305
00306 m_container->m_tetrahedron[ indices[i] ] = m_container->m_tetrahedron[ lastTetrahedron ];
00307 m_container->m_tetrahedron.resize( lastTetrahedron );
00308 }
00309
00310 if ( (!triangleToBeRemoved.empty()) || (!edgeToBeRemoved.empty()))
00311 {
00312 if (!triangleToBeRemoved.empty())
00313 {
00315 removeTrianglesWarning(triangleToBeRemoved);
00316 }
00317
00318 if (!edgeToBeRemoved.empty())
00319 {
00321 removeEdgesWarning(edgeToBeRemoved);
00322 }
00323
00324 propagateTopologicalChanges();
00325
00326 if (!triangleToBeRemoved.empty())
00327 {
00329 removeTrianglesProcess(triangleToBeRemoved, false, false);
00330
00331 }
00332
00333 if (!edgeToBeRemoved.empty())
00334 {
00336 removeEdgesProcess(edgeToBeRemoved, false);
00337 }
00338 }
00339
00340 if (!vertexToBeRemoved.empty())
00341 {
00342 removePointsWarning(vertexToBeRemoved);
00343 propagateTopologicalChanges();
00344 removePointsProcess(vertexToBeRemoved);
00345 }
00346 }
00347
00348 void TetrahedronSetTopologyModifier::addPointsProcess(const unsigned int nPoints)
00349 {
00350
00351 TriangleSetTopologyModifier::addPointsProcess( nPoints );
00352
00353 if(m_container->hasTetrahedronVertexShell())
00354 m_container->m_tetrahedronVertexShell.resize( m_container->getNbPoints() );
00355 }
00356
00357 void TetrahedronSetTopologyModifier::addEdgesProcess(const sofa::helper::vector< Edge > &edges)
00358 {
00359
00360 TriangleSetTopologyModifier::addEdgesProcess( edges );
00361
00362 if(m_container->hasTetrahedronEdgeShell())
00363 m_container->m_tetrahedronEdgeShell.resize( m_container->getNumberOfEdges() );
00364 }
00365
00366 void TetrahedronSetTopologyModifier::addTrianglesProcess(const sofa::helper::vector< Triangle > &triangles)
00367 {
00368
00369 TriangleSetTopologyModifier::addTrianglesProcess( triangles );
00370
00371 if(m_container->hasTetrahedronTriangleShell())
00372 m_container->m_tetrahedronTriangleShell.resize( m_container->getNumberOfTriangles() );
00373 }
00374
00375 void TetrahedronSetTopologyModifier::removePointsProcess( sofa::helper::vector<unsigned int> &indices,
00376 const bool removeDOF)
00377 {
00378 if(m_container->hasTetrahedra())
00379 {
00380 if(!m_container->hasTetrahedronVertexShell())
00381 {
00382 m_container->createTetrahedronVertexShellArray();
00383 }
00384
00385 unsigned int lastPoint = m_container->getNbPoints() - 1;
00386 for (unsigned int i=0; i<indices.size(); ++i, --lastPoint)
00387 {
00388
00389
00390 for (sofa::helper::vector<unsigned int>::iterator itt=m_container->m_tetrahedronVertexShell[lastPoint].begin();
00391 itt!=m_container->m_tetrahedronVertexShell[lastPoint].end(); ++itt)
00392 {
00393 unsigned int vertexIndex = m_container->getVertexIndexInTetrahedron(m_container->m_tetrahedron[(*itt)],lastPoint);
00394 m_container->m_tetrahedron[(*itt)][vertexIndex]=indices[i];
00395 }
00396
00397
00398 m_container->m_tetrahedronVertexShell[ indices[i] ] = m_container->m_tetrahedronVertexShell[ lastPoint ];
00399 }
00400
00401 m_container->m_tetrahedronVertexShell.resize( m_container->m_tetrahedronVertexShell.size() - indices.size() );
00402 }
00403
00404
00405
00406 TriangleSetTopologyModifier::removePointsProcess( indices, removeDOF );
00407 }
00408
00409 void TetrahedronSetTopologyModifier::removeEdgesProcess( const sofa::helper::vector<unsigned int> &indices,
00410 const bool removeIsolatedItems)
00411 {
00412 if(!m_container->hasEdges())
00413 return;
00414
00415 if (m_container->hasTetrahedronEdges())
00416 {
00417 if(!m_container->hasTetrahedronEdgeShell())
00418 m_container->createTetrahedronEdgeShellArray();
00419
00420 unsigned int lastEdge = m_container->getNumberOfEdges() - 1;
00421 for (unsigned int i=0; i<indices.size(); ++i, --lastEdge)
00422 {
00423 for (sofa::helper::vector<unsigned int>::iterator itt=m_container->m_tetrahedronEdgeShell[lastEdge].begin();
00424 itt!=m_container->m_tetrahedronEdgeShell[lastEdge].end(); ++itt)
00425 {
00426 unsigned int edgeIndex=m_container->getEdgeIndexInTetrahedron(m_container->m_tetrahedronEdge[(*itt)],lastEdge);
00427 m_container->m_tetrahedronEdge[(*itt)][edgeIndex]=indices[i];
00428 }
00429
00430
00431 m_container->m_tetrahedronEdgeShell[ indices[i] ] = m_container->m_tetrahedronEdgeShell[ lastEdge ];
00432 }
00433
00434 m_container->m_tetrahedronEdgeShell.resize( m_container->m_tetrahedronEdgeShell.size() - indices.size() );
00435 }
00436
00437
00438 TriangleSetTopologyModifier::removeEdgesProcess( indices, removeIsolatedItems );
00439 }
00440
00441 void TetrahedronSetTopologyModifier::removeTrianglesProcess( const sofa::helper::vector<unsigned int> &indices,
00442 const bool removeIsolatedEdges,
00443 const bool removeIsolatedPoints)
00444 {
00445 if(!m_container->hasTriangles())
00446 return;
00447
00448 if (m_container->hasTetrahedronTriangles())
00449 {
00450 if(!m_container->hasTetrahedronTriangleShell())
00451 m_container->createTetrahedronTriangleShellArray();
00452
00453 unsigned int lastTriangle = m_container->m_tetrahedronTriangleShell.size() - 1;
00454 for (unsigned int i = 0; i < indices.size(); ++i, --lastTriangle)
00455 {
00456 for (sofa::helper::vector<unsigned int>::iterator itt=m_container->m_tetrahedronTriangleShell[lastTriangle].begin();
00457 itt!=m_container->m_tetrahedronTriangleShell[lastTriangle].end(); ++itt)
00458 {
00459 unsigned int triangleIndex=m_container->getTriangleIndexInTetrahedron(m_container->m_tetrahedronTriangle[(*itt)],lastTriangle);
00460 m_container->m_tetrahedronTriangle[(*itt)][triangleIndex] = indices[i];
00461 }
00462
00463
00464 m_container->m_tetrahedronTriangleShell[ indices[i] ] = m_container->m_tetrahedronTriangleShell[ lastTriangle ];
00465 }
00466 m_container->m_tetrahedronTriangleShell.resize( m_container->m_tetrahedronTriangleShell.size() - indices.size() );
00467 }
00468
00469
00470 TriangleSetTopologyModifier::removeTrianglesProcess( indices, removeIsolatedEdges, removeIsolatedPoints );
00471 }
00472
00473 void TetrahedronSetTopologyModifier::renumberPointsProcess( const sofa::helper::vector<unsigned int> &index,
00474 const sofa::helper::vector<unsigned int> &inv_index,
00475 const bool renumberDOF)
00476 {
00477 if(m_container->hasTetrahedra())
00478 {
00479 if(m_container->hasTetrahedronVertexShell())
00480 {
00481 sofa::helper::vector< sofa::helper::vector< unsigned int > > tetrahedronVertexShell_cp = m_container->m_tetrahedronVertexShell;
00482 for (unsigned int i = 0; i < index.size(); ++i)
00483 {
00484 m_container->m_tetrahedronVertexShell[i] = tetrahedronVertexShell_cp[ index[i] ];
00485 }
00486 }
00487
00488 for (unsigned int i=0; i<m_container->m_tetrahedron.size(); ++i)
00489 {
00490 m_container->m_tetrahedron[i][0] = inv_index[ m_container->m_tetrahedron[i][0] ];
00491 m_container->m_tetrahedron[i][1] = inv_index[ m_container->m_tetrahedron[i][1] ];
00492 m_container->m_tetrahedron[i][2] = inv_index[ m_container->m_tetrahedron[i][2] ];
00493 m_container->m_tetrahedron[i][3] = inv_index[ m_container->m_tetrahedron[i][3] ];
00494 }
00495 }
00496
00497
00498 TriangleSetTopologyModifier::renumberPointsProcess( index, inv_index, renumberDOF );
00499 }
00500
00501 void TetrahedronSetTopologyModifier::removeTetrahedra(sofa::helper::vector< unsigned int >& tetrahedra)
00502 {
00503 removeTetrahedraWarning(tetrahedra);
00504
00505
00506 propagateTopologicalChanges();
00507
00508
00509 removeTetrahedraProcess( tetrahedra ,true);
00510
00511 m_container->checkTopology();
00512 }
00513
00514 void TetrahedronSetTopologyModifier::removeItems(sofa::helper::vector< unsigned int >& items)
00515 {
00516 removeTetrahedra(items);
00517 }
00518
00519 void TetrahedronSetTopologyModifier::renumberPoints( const sofa::helper::vector<unsigned int> &index,
00520 const sofa::helper::vector<unsigned int> &inv_index)
00521 {
00523 renumberPointsWarning(index, inv_index);
00524
00525 propagateTopologicalChanges();
00526
00527 renumberPointsProcess(index, inv_index);
00528
00529 m_container->checkTopology();
00530 }
00531
00532 }
00533
00534 }
00535
00536 }
00537