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
00026 #include <sofa/component/topology/TetrahedronSetTopologyContainer.h>
00027 #include <sofa/core/ObjectFactory.h>
00028
00029 #include <sofa/component/MeshLoader.h>
00030
00031 namespace sofa
00032 {
00033
00034 namespace component
00035 {
00036
00037 namespace topology
00038 {
00039 using namespace std;
00040 using namespace sofa::defaulttype;
00041
00042 SOFA_DECL_CLASS(TetrahedronSetTopologyContainer)
00043 int TetrahedronSetTopologyContainerClass = core::RegisterObject("Tetrahedron set topology container")
00044 .add< TetrahedronSetTopologyContainer >()
00045 ;
00046
00047 const unsigned int tetrahedronEdgeArray[6][2] = {{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}};
00048
00049 TetrahedronSetTopologyContainer::TetrahedronSetTopologyContainer()
00050 : TriangleSetTopologyContainer()
00051 {}
00052
00053 TetrahedronSetTopologyContainer::TetrahedronSetTopologyContainer(const sofa::helper::vector< Tetrahedron >& tetrahedra )
00054 : TriangleSetTopologyContainer()
00055 , m_tetrahedron( tetrahedra )
00056 {
00057 for (unsigned int i=0; i<m_tetrahedron.size(); ++i)
00058 {
00059 for(unsigned int j=0; j<4; ++j)
00060 {
00061 int a = m_tetrahedron[i][j];
00062 if (a >= (int)nbPoints) nbPoints = a+1;
00063 }
00064 }
00065 }
00066
00067 void TetrahedronSetTopologyContainer::addTetra( int a, int b, int c, int d )
00068 {
00069 m_tetrahedron.push_back(Tetra(a,b,c,d));
00070 if (a >= (int)nbPoints) nbPoints = a+1;
00071 if (b >= (int)nbPoints) nbPoints = b+1;
00072 if (c >= (int)nbPoints) nbPoints = c+1;
00073 if (d >= (int)nbPoints) nbPoints = d+1;
00074 }
00075
00076 void TetrahedronSetTopologyContainer::init()
00077 {
00078 TriangleSetTopologyContainer::init();
00079 }
00080
00081 void TetrahedronSetTopologyContainer::loadFromMeshLoader(sofa::component::MeshLoader* loader)
00082 {
00083
00084 PointSetTopologyContainer::loadFromMeshLoader(loader);
00085 m_tetrahedron = loader->getTetras();
00086 }
00087
00088 void TetrahedronSetTopologyContainer::createTetrahedronSetArray()
00089 {
00090 #ifndef NDEBUG
00091 cout << "Error. [TetrahedronSetTopologyContainer::createTetrahedronSetArray] This method must be implemented by a child topology." << endl;
00092 #endif
00093 }
00094
00095 void TetrahedronSetTopologyContainer::createEdgeSetArray()
00096 {
00097 if(hasEdges())
00098 {
00099 EdgeSetTopologyContainer::clear();
00100
00101 clearTriangleEdges();
00102 clearTriangleEdgeShell();
00103
00104 clearTetrahedronEdges();
00105 clearTetrahedronEdgeShell();
00106 }
00107
00108
00109 std::map<Edge,unsigned int> edgeMap;
00110
00112 for (unsigned int i = 0; i < m_tetrahedron.size(); ++i)
00113 {
00114 Tetrahedron &t = m_tetrahedron[i];
00115 for (unsigned int j=0; j<6; ++j)
00116 {
00117 const unsigned int v1 = t[tetrahedronEdgeArray[j][0]];
00118 const unsigned int v2 = t[tetrahedronEdgeArray[j][1]];
00119 const Edge e((v1<v2) ? Edge(v1,v2) : Edge(v2,v1));
00120
00121 if (edgeMap.find(e)==edgeMap.end())
00122 {
00123
00124 const int edgeIndex = edgeMap.size();
00125 edgeMap[e] = edgeIndex;
00126 m_edge.push_back(e);
00127 }
00128 }
00129 }
00130 }
00131
00132 void TetrahedronSetTopologyContainer::createTetrahedronEdgeArray()
00133 {
00134 if(!hasEdges())
00135 createEdgeSetArray();
00136
00137 if(hasTetrahedronEdges())
00138 clearTetrahedronEdges();
00139
00140 m_tetrahedronEdge.resize( getNumberOfTetrahedra());
00141
00142 for (unsigned int i=0; i<m_tetrahedron.size(); ++i)
00143 {
00144 Tetrahedron &t = m_tetrahedron[i];
00145
00146
00147 for (unsigned int j=0; j<6; ++j)
00148 {
00149 int edgeIndex = getEdgeIndex(t[tetrahedronEdgeArray[j][0]],
00150 t[tetrahedronEdgeArray[j][1]]);
00151 m_tetrahedronEdge[i][j] = (unsigned int) edgeIndex;
00152 }
00153 }
00154 }
00155
00156 void TetrahedronSetTopologyContainer::createTriangleSetArray()
00157 {
00158 if(hasTriangles())
00159 {
00160 TriangleSetTopologyContainer::clear();
00161 clearTriangles();
00162 clearTetrahedronTriangles();
00163 clearTetrahedronTriangleShell();
00164 }
00165
00166
00167 std::map<Triangle,unsigned int> triangleMap;
00168
00170 for (unsigned int i=0; i<m_tetrahedron.size(); ++i)
00171 {
00172 Tetrahedron &t = m_tetrahedron[i];
00173
00174 for (unsigned int j=0; j<4; ++j)
00175 {
00176 unsigned int v[3];
00177
00178 if (j%2)
00179 {
00180 v[0]=t[(j+1)%4];
00181 v[1]=t[(j+2)%4];
00182 v[2]=t[(j+3)%4];
00183 }
00184 else
00185 {
00186 v[0]=t[(j+1)%4];
00187 v[2]=t[(j+2)%4];
00188 v[1]=t[(j+3)%4];
00189 }
00190
00191
00192 while ((v[0]>v[1]) || (v[0]>v[2]))
00193 {
00194 unsigned int val=v[0];
00195 v[0]=v[1];
00196 v[1]=v[2];
00197 v[2]=val;
00198 }
00199
00200
00201 Triangle tr = helper::make_array<unsigned int>(v[0], v[2], v[1]);
00202
00203 if (triangleMap.find(tr) == triangleMap.end())
00204 {
00205
00206 tr = helper::make_array<unsigned int>(v[0], v[1], v[2]);
00207 triangleMap[tr] = triangleMap.size();
00208 m_triangle.push_back(tr);
00209 }
00210 }
00211 }
00212 }
00213
00214 void TetrahedronSetTopologyContainer::createTetrahedronTriangleArray()
00215 {
00216 if(!hasTriangles())
00217 createTriangleSetArray();
00218
00219 if(hasTetrahedronTriangles())
00220 clearTetrahedronTriangles();
00221
00222 m_tetrahedronTriangle.resize( getNumberOfTetrahedra());
00223
00224 for(unsigned int i = 0; i < m_tetrahedron.size(); ++i)
00225 {
00226 Tetrahedron &t=m_tetrahedron[i];
00227
00228
00229 for (unsigned int j=0; j<4; ++j)
00230 {
00231 const int triangleIndex = getTriangleIndex(t[(j+1)%4], t[(j+2)%4], t[(j+3)%4]);
00232 m_tetrahedronTriangle[i][j] = (unsigned int) triangleIndex;
00233 }
00234 }
00235 }
00236
00237 void TetrahedronSetTopologyContainer::createTetrahedronVertexShellArray ()
00238 {
00239 if(hasTetrahedronVertexShell())
00240 clearTetrahedronVertexShell();
00241
00242 m_tetrahedronVertexShell.resize( getNbPoints() );
00243
00244 for (unsigned int i = 0; i < m_tetrahedron.size(); ++i)
00245 {
00246
00247 for (unsigned int j=0; j<4; ++j)
00248 {
00249 m_tetrahedronVertexShell[ m_tetrahedron[i][j] ].push_back( i );
00250 }
00251 }
00252 }
00253
00254 void TetrahedronSetTopologyContainer::createTetrahedronEdgeShellArray ()
00255 {
00256 if(!hasTetrahedronEdges())
00257 createTetrahedronEdgeArray();
00258
00259 if(hasTetrahedronEdgeShell())
00260 clearTetrahedronEdgeShell();
00261
00262 m_tetrahedronEdgeShell.resize(getNumberOfEdges());
00263
00264 for (unsigned int i=0; i<m_tetrahedron.size(); ++i)
00265 {
00266
00267 for (unsigned int j=0; j<6; ++j)
00268 {
00269 m_tetrahedronEdgeShell[ m_tetrahedronEdge[i][j] ].push_back( i );
00270 }
00271 }
00272 }
00273
00274 void TetrahedronSetTopologyContainer::createTetrahedronTriangleShellArray ()
00275 {
00276 if(!hasTetrahedronTriangles())
00277 createTetrahedronTriangleArray();
00278
00279 if(hasTetrahedronTriangleShell())
00280 clearTetrahedronTriangleShell();
00281
00282 m_tetrahedronTriangleShell.resize( getNumberOfTriangles());
00283
00284 for (unsigned int i=0; i<m_tetrahedron.size(); ++i)
00285 {
00286
00287 for (unsigned int j=0; j<4; ++j)
00288 {
00289 m_tetrahedronTriangleShell[ m_tetrahedronTriangle[i][j] ].push_back( i );
00290 }
00291 }
00292 }
00293
00294 const sofa::helper::vector<Tetrahedron> &TetrahedronSetTopologyContainer::getTetrahedronArray()
00295 {
00296 if (!hasTetrahedra() && getNbPoints()>0)
00297 {
00298 #ifndef NDEBUG
00299 cout << "[TetrahedronSetTopologyContainer::getTetrahedronArray] creating tetrahedron array." << endl;
00300 #endif
00301 createTetrahedronSetArray();
00302 }
00303
00304 return m_tetrahedron;
00305 }
00306
00307 int TetrahedronSetTopologyContainer::getTetrahedronIndex(PointID v1, PointID v2, PointID v3, PointID v4)
00308 {
00309 if(!hasTetrahedronVertexShell())
00310 createTetrahedronVertexShellArray();
00311
00312 sofa::helper::vector<unsigned int> set1 = getTetrahedronVertexShell(v1);
00313 sofa::helper::vector<unsigned int> set2 = getTetrahedronVertexShell(v2);
00314 sofa::helper::vector<unsigned int> set3 = getTetrahedronVertexShell(v3);
00315 sofa::helper::vector<unsigned int> set4 = getTetrahedronVertexShell(v4);
00316
00317 sort(set1.begin(), set1.end());
00318 sort(set2.begin(), set2.end());
00319 sort(set3.begin(), set3.end());
00320 sort(set4.begin(), set4.end());
00321
00322
00323 sofa::helper::vector<unsigned int> out1(set1.size()+set2.size());
00324 sofa::helper::vector<unsigned int>::iterator result1;
00325 result1 = std::set_intersection(set1.begin(),set1.end(),set2.begin(),set2.end(),out1.begin());
00326 out1.erase(result1,out1.end());
00327
00328 sofa::helper::vector<unsigned int> out2(set3.size()+out1.size());
00329 sofa::helper::vector<unsigned int>::iterator result2;
00330 result2 = std::set_intersection(set3.begin(),set3.end(),out1.begin(),out1.end(),out2.begin());
00331 out2.erase(result2,out2.end());
00332
00333 sofa::helper::vector<unsigned int> out3(set4.size()+out2.size());
00334 sofa::helper::vector<unsigned int>::iterator result3;
00335 result3 = std::set_intersection(set4.begin(),set4.end(),out2.begin(),out2.end(),out3.begin());
00336 out3.erase(result3,out3.end());
00337
00338 assert(out3.size()==0 || out3.size()==1);
00339
00340 if (out3.size()==1)
00341 return (int) (out3[0]);
00342 else
00343 return -1;
00344 }
00345
00346 unsigned int TetrahedronSetTopologyContainer::getNumberOfTetrahedra() const
00347 {
00348 return m_tetrahedron.size();
00349 }
00350
00351 const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TetrahedronSetTopologyContainer::getTetrahedronVertexShellArray()
00352 {
00353 if (!hasTetrahedronVertexShell())
00354 createTetrahedronVertexShellArray();
00355
00356 return m_tetrahedronVertexShell;
00357 }
00358
00359 const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TetrahedronSetTopologyContainer::getTetrahedronEdgeShellArray()
00360 {
00361 if (!hasTetrahedronEdgeShell())
00362 createTetrahedronEdgeShellArray();
00363
00364 return m_tetrahedronEdgeShell;
00365 }
00366
00367 const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TetrahedronSetTopologyContainer::getTetrahedronTriangleShellArray()
00368 {
00369 if (!hasTetrahedronTriangleShell())
00370 createTetrahedronTriangleShellArray();
00371
00372 return m_tetrahedronTriangleShell;
00373 }
00374
00375 const sofa::helper::vector< TetrahedronEdges> &TetrahedronSetTopologyContainer::getTetrahedronEdgeArray()
00376 {
00377 if (!hasTetrahedronEdges())
00378 createTetrahedronEdgeArray();
00379
00380 return m_tetrahedronEdge;
00381 }
00382
00383 Edge TetrahedronSetTopologyContainer::getLocalTetrahedronEdges (const unsigned int i) const
00384 {
00385 assert(i<6);
00386 return Edge (tetrahedronEdgeArray[i][0], tetrahedronEdgeArray[i][1]);
00387 }
00388
00389 const sofa::helper::vector< TetrahedronTriangles> &TetrahedronSetTopologyContainer::getTetrahedronTriangleArray()
00390 {
00391 if (!hasTetrahedronTriangles())
00392 createTetrahedronTriangleArray();
00393
00394 return m_tetrahedronTriangle;
00395 }
00396
00397 const sofa::helper::vector< unsigned int > &TetrahedronSetTopologyContainer::getTetrahedronVertexShell(const unsigned int i)
00398 {
00399 if (!hasTetrahedronVertexShell())
00400 createTetrahedronVertexShellArray();
00401
00402 assert(i < m_tetrahedronVertexShell.size());
00403
00404 return m_tetrahedronVertexShell[i];
00405 }
00406
00407 const sofa::helper::vector< unsigned int > &TetrahedronSetTopologyContainer::getTetrahedronEdgeShell(const unsigned int i)
00408 {
00409 if (!hasTetrahedronEdgeShell())
00410 createTetrahedronEdgeShellArray();
00411
00412 assert(i < m_tetrahedronEdgeShell.size());
00413
00414 return m_tetrahedronEdgeShell[i];
00415 }
00416
00417 const sofa::helper::vector< unsigned int > &TetrahedronSetTopologyContainer::getTetrahedronTriangleShell(const unsigned int i)
00418 {
00419 if (!hasTetrahedronTriangleShell())
00420 createTetrahedronTriangleShellArray();
00421
00422 assert(i < m_tetrahedronTriangleShell.size());
00423
00424 return m_tetrahedronTriangleShell[i];
00425 }
00426
00427 const TetrahedronEdges &TetrahedronSetTopologyContainer::getTetrahedronEdges(const unsigned int i)
00428 {
00429 if (!hasTetrahedronEdges())
00430 createTetrahedronEdgeArray();
00431
00432 assert(i < m_tetrahedronEdge.size());
00433
00434 return m_tetrahedronEdge[i];
00435 }
00436
00437 const TetrahedronTriangles &TetrahedronSetTopologyContainer::getTetrahedronTriangles(const unsigned int i)
00438 {
00439 if (!hasTetrahedronTriangles())
00440 createTetrahedronTriangleArray();
00441
00442 assert(i < m_tetrahedronTriangle.size());
00443
00444 return m_tetrahedronTriangle[i];
00445 }
00446
00447 int TetrahedronSetTopologyContainer::getVertexIndexInTetrahedron(const Tetrahedron &t,
00448 unsigned int vertexIndex) const
00449 {
00450 if (t[0]==vertexIndex)
00451 return 0;
00452 else if (t[1]==vertexIndex)
00453 return 1;
00454 else if (t[2]==vertexIndex)
00455 return 2;
00456 else if (t[3]==vertexIndex)
00457 return 3;
00458 else
00459 return -1;
00460 }
00461
00462 int TetrahedronSetTopologyContainer::getEdgeIndexInTetrahedron(const TetrahedronEdges &t,
00463 const unsigned int edgeIndex) const
00464 {
00465 if (t[0]==edgeIndex)
00466 return 0;
00467 else if (t[1]==edgeIndex)
00468 return 1;
00469 else if (t[2]==edgeIndex)
00470 return 2;
00471 else if (t[3]==edgeIndex)
00472 return 3;
00473 else if (t[4]==edgeIndex)
00474 return 4;
00475 else if (t[5]==edgeIndex)
00476 return 5;
00477 else
00478 return -1;
00479 }
00480
00481 int TetrahedronSetTopologyContainer::getTriangleIndexInTetrahedron(const TetrahedronTriangles &t,
00482 const unsigned int triangleIndex) const
00483 {
00484 if (t[0]==triangleIndex)
00485 return 0;
00486 else if (t[1]==triangleIndex)
00487 return 1;
00488 else if (t[2]==triangleIndex)
00489 return 2;
00490 else if (t[3]==triangleIndex)
00491 return 3;
00492 else
00493 return -1;
00494 }
00495
00496 sofa::helper::vector< unsigned int > &TetrahedronSetTopologyContainer::getTetrahedronEdgeShellForModification(const unsigned int i)
00497 {
00498 if (!hasTetrahedronEdgeShell())
00499 createTetrahedronEdgeShellArray();
00500
00501 assert(i < m_tetrahedronEdgeShell.size());
00502
00503 return m_tetrahedronEdgeShell[i];
00504 }
00505
00506 sofa::helper::vector< unsigned int > &TetrahedronSetTopologyContainer::getTetrahedronVertexShellForModification(const unsigned int i)
00507 {
00508 if (!hasTetrahedronVertexShell())
00509 createTetrahedronVertexShellArray();
00510
00511 assert(i < m_tetrahedronVertexShell.size());
00512
00513 return m_tetrahedronVertexShell[i];
00514 }
00515
00516 bool TetrahedronSetTopologyContainer::checkTopology() const
00517 {
00518 #ifndef NDEBUG
00519 bool ret = true;
00520
00521 if(hasTetrahedronVertexShell())
00522 {
00523 for (unsigned int i=0; i<m_tetrahedronVertexShell.size(); ++i)
00524 {
00525 const sofa::helper::vector<unsigned int> &tvs = m_tetrahedronVertexShell[i];
00526 for (unsigned int j=0; j<tvs.size(); ++j)
00527 {
00528 bool check_tetra_vertex_shell = (m_tetrahedron[tvs[j]][0]==i)
00529 || (m_tetrahedron[tvs[j]][1]==i)
00530 || (m_tetrahedron[tvs[j]][2]==i)
00531 || (m_tetrahedron[tvs[j]][3]==i);
00532 if(!check_tetra_vertex_shell)
00533 {
00534 std::cout << "*** CHECK FAILED : check_tetra_vertex_shell, i = " << i << " , j = " << j << std::endl;
00535 ret = false;
00536 }
00537 }
00538 }
00539 }
00540
00541 if (hasTetrahedronEdgeShell())
00542 {
00543 for (unsigned int i=0; i<m_tetrahedronEdgeShell.size(); ++i)
00544 {
00545 const sofa::helper::vector<unsigned int> &tes=m_tetrahedronEdgeShell[i];
00546 for (unsigned int j=0; j<tes.size(); ++j)
00547 {
00548 bool check_tetra_edge_shell = (m_tetrahedronEdge[tes[j]][0]==i)
00549 || (m_tetrahedronEdge[tes[j]][1]==i)
00550 || (m_tetrahedronEdge[tes[j]][2]==i)
00551 || (m_tetrahedronEdge[tes[j]][3]==i)
00552 || (m_tetrahedronEdge[tes[j]][4]==i)
00553 || (m_tetrahedronEdge[tes[j]][5]==i);
00554 if(!check_tetra_edge_shell)
00555 {
00556 std::cout << "*** CHECK FAILED : check_tetra_edge_shell, i = " << i << " , j = " << j << std::endl;
00557 ret = false;
00558 }
00559 }
00560 }
00561 }
00562
00563 if (hasTetrahedronTriangleShell())
00564 {
00565 for (unsigned int i=0; i<m_tetrahedronTriangleShell.size(); ++i)
00566 {
00567 const sofa::helper::vector<unsigned int> &tes=m_tetrahedronTriangleShell[i];
00568 for (unsigned int j=0; j<tes.size(); ++j)
00569 {
00570 bool check_tetra_triangle_shell = (m_tetrahedronTriangle[tes[j]][0]==i)
00571 || (m_tetrahedronTriangle[tes[j]][1]==i)
00572 || (m_tetrahedronTriangle[tes[j]][2]==i)
00573 || (m_tetrahedronTriangle[tes[j]][3]==i);
00574 if(!check_tetra_triangle_shell)
00575 {
00576 std::cout << "*** CHECK FAILED : check_tetra_triangle_shell, i = " << i << " , j = " << j << std::endl;
00577 ret = false;
00578 }
00579 }
00580 }
00581 }
00582
00583 return ret && TriangleSetTopologyContainer::checkTopology();
00584 #else
00585 return true;
00586 #endif
00587 }
00588
00589 bool TetrahedronSetTopologyContainer::hasTetrahedra() const
00590 {
00591 return !m_tetrahedron.empty();
00592 }
00593
00594 bool TetrahedronSetTopologyContainer::hasTetrahedronEdges() const
00595 {
00596 return !m_tetrahedronEdge.empty();
00597 }
00598
00599 bool TetrahedronSetTopologyContainer::hasTetrahedronTriangles() const
00600 {
00601 return !m_tetrahedronTriangle.empty();
00602 }
00603
00604 bool TetrahedronSetTopologyContainer::hasTetrahedronVertexShell() const
00605 {
00606 return !m_tetrahedronVertexShell.empty();
00607 }
00608
00609 bool TetrahedronSetTopologyContainer::hasTetrahedronEdgeShell() const
00610 {
00611 return !m_tetrahedronEdgeShell.empty();
00612 }
00613
00614 bool TetrahedronSetTopologyContainer::hasTetrahedronTriangleShell() const
00615 {
00616 return !m_tetrahedronTriangleShell.empty();
00617 }
00618
00619 void TetrahedronSetTopologyContainer::clearTetrahedra()
00620 {
00621 m_tetrahedron.clear();
00622 }
00623
00624 void TetrahedronSetTopologyContainer::clearTetrahedronEdges()
00625 {
00626 m_tetrahedronEdge.clear();
00627 }
00628
00629 void TetrahedronSetTopologyContainer::clearTetrahedronTriangles()
00630 {
00631 m_tetrahedronTriangle.clear();
00632 }
00633
00634 void TetrahedronSetTopologyContainer::clearTetrahedronVertexShell()
00635 {
00636 m_tetrahedronVertexShell.clear();
00637 }
00638
00639 void TetrahedronSetTopologyContainer::clearTetrahedronEdgeShell()
00640 {
00641 m_tetrahedronEdgeShell.clear();
00642 }
00643
00644 void TetrahedronSetTopologyContainer::clearTetrahedronTriangleShell()
00645 {
00646 m_tetrahedronTriangleShell.clear();
00647 }
00648
00649 void TetrahedronSetTopologyContainer::clear()
00650 {
00651 clearTetrahedronVertexShell();
00652 clearTetrahedronEdgeShell();
00653 clearTetrahedronTriangleShell();
00654 clearTetrahedronEdges();
00655 clearTetrahedronTriangles();
00656 clearTetrahedra();
00657
00658 TriangleSetTopologyContainer::clear();
00659 }
00660
00661 }
00662
00663 }
00664
00665 }
00666