TriangleSetTopologyContainer.cpp
Go to the documentation of this file.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/TriangleSetTopologyContainer.h>
00026
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
00043 SOFA_DECL_CLASS(TriangleSetTopologyContainer)
00044 int TriangleSetTopologyContainerClass = core::RegisterObject("Triangle set topology container")
00045 .add< TriangleSetTopologyContainer >()
00046 ;
00047
00048 TriangleSetTopologyContainer::TriangleSetTopologyContainer()
00049 : EdgeSetTopologyContainer()
00050 {}
00051
00052 TriangleSetTopologyContainer::TriangleSetTopologyContainer(const sofa::helper::vector< Triangle > &triangles )
00053 : EdgeSetTopologyContainer()
00054 , m_triangle( triangles )
00055 {
00056 for (unsigned int i=0; i<m_triangle.size(); ++i)
00057 {
00058 for(unsigned int j=0; j<3; ++j)
00059 {
00060 int a = m_triangle[i][j];
00061 if (a >= (int)nbPoints)
00062 nbPoints = a+1;
00063 }
00064 }
00065 }
00066
00067 void TriangleSetTopologyContainer::init()
00068 {
00069 EdgeSetTopologyContainer::init();
00070 }
00071
00072 void TriangleSetTopologyContainer::loadFromMeshLoader(sofa::component::MeshLoader* loader)
00073 {
00074
00075 PointSetTopologyContainer::loadFromMeshLoader(loader);
00076 m_triangle = loader->getTriangles();
00077 }
00078
00079 void TriangleSetTopologyContainer::addTriangle( int a, int b, int c )
00080 {
00081 m_triangle.push_back(Triangle(a,b,c));
00082 if (a >= (int)nbPoints) nbPoints = a+1;
00083 if (b >= (int)nbPoints) nbPoints = b+1;
00084 if (c >= (int)nbPoints) nbPoints = c+1;
00085 }
00086
00087 void TriangleSetTopologyContainer::createTriangleSetArray()
00088 {
00089 #ifndef NDEBUG
00090 cout << "Error. [TriangleSetTopologyContainer::createTriangleSetArray] This method must be implemented by a child topology." << endl;
00091 #endif
00092 }
00093
00094 void TriangleSetTopologyContainer::createTriangleVertexShellArray ()
00095 {
00096 if(!hasTriangles())
00097 {
00098 #ifndef NDEBUG
00099 cout << "Warning. [TriangleSetTopologyContainer::createTriangleVertexShellArray] triangle array is empty." << endl;
00100 #endif
00101 createTriangleSetArray();
00102 }
00103
00104 if(hasTriangleVertexShell())
00105 {
00106 clearTriangleVertexShell();
00107 }
00108
00109 m_triangleVertexShell.resize( getNbPoints() );
00110
00111 for (unsigned int i = 0; i < m_triangle.size(); ++i)
00112 {
00113
00114 for (unsigned int j=0; j<3; ++j)
00115 m_triangleVertexShell[ m_triangle[i][j] ].push_back( i );
00116 }
00117 }
00118
00119 void TriangleSetTopologyContainer::createTriangleEdgeShellArray ()
00120 {
00121 if(!hasTriangles())
00122 {
00123 #ifndef NDEBUG
00124 cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeShellArray] triangle array is empty." << endl;
00125 #endif
00126 createTriangleSetArray();
00127 }
00128
00129 if(!hasEdges())
00130 {
00131 #ifndef NDEBUG
00132 cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeShellArray] edge array is empty." << endl;
00133 #endif
00134 createEdgeSetArray();
00135 }
00136
00137 if(!hasTriangleEdges())
00138 createTriangleEdgeArray();
00139
00140 const unsigned int numTriangles = getNumberOfTriangles();
00141 const unsigned int numEdges = getNumberOfEdges();
00142
00143 if(hasTriangleEdgeShell())
00144 {
00145 clearTriangleEdgeShell();
00146 }
00147
00148 m_triangleEdgeShell.resize( numEdges );
00149
00150 for (unsigned int i = 0; i < numTriangles; ++i)
00151 {
00152
00153 for (unsigned int j=0; j<3; ++j)
00154 {
00155 m_triangleEdgeShell[ m_triangleEdge[i][j] ].push_back( i );
00156 }
00157 }
00158 }
00159
00160 void TriangleSetTopologyContainer::createEdgeSetArray()
00161 {
00162 if(!hasTriangles())
00163 {
00164 #ifndef NDEBUG
00165 cout << "Warning. [TriangleSetTopologyContainer::createEdgeSetArray] triangle array is empty." << endl;
00166 #endif
00167 createTriangleSetArray();
00168 }
00169
00170 if(hasEdges())
00171 {
00172 #ifndef NDEBUG
00173 cout << "Warning. [TriangleSetTopologyContainer::createEdgeSetArray] edge array is not empty." << endl;
00174 #endif
00175
00176
00177 EdgeSetTopologyContainer::clear();
00178
00179 if(hasTriangleEdges())
00180 clearTriangleEdges();
00181
00182 if(hasTriangleEdgeShell())
00183 clearTriangleEdgeShell();
00184 }
00185
00186
00187 std::map<Edge, unsigned int> edgeMap;
00188
00189 for (unsigned int i=0; i<m_triangle.size(); ++i)
00190 {
00191 const Triangle &t = m_triangle[i];
00192 for(unsigned int j=0; j<3; ++j)
00193 {
00194 const unsigned int v1 = t[(j+1)%3];
00195 const unsigned int v2 = t[(j+2)%3];
00196
00197
00198 const Edge e = ((v1<v2) ? Edge(v1,v2) : Edge(v2,v1));
00199
00200 if(edgeMap.find(e) == edgeMap.end())
00201 {
00202
00203 const int edgeIndex = edgeMap.size();
00204 edgeMap[e] = edgeIndex;
00205 m_edge.push_back(e);
00206 }
00207 }
00208 }
00209 }
00210
00211 void TriangleSetTopologyContainer::createTriangleEdgeArray()
00212 {
00213 if(!hasTriangles())
00214 {
00215 #ifndef NDEBUG
00216 cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeArray] triangle array is empty." << endl;
00217 #endif
00218 createTriangleSetArray();
00219 }
00220
00221 if(!hasEdges())
00222 {
00223 #ifndef NDEBUG
00224 cout << "Warning. [TriangleSetTopologyContainer::createTriangleEdgeArray] edge array is empty." << endl;
00225 #endif
00226 createEdgeSetArray();
00227 }
00228
00229 if(hasTriangleEdges())
00230 clearTriangleEdges();
00231
00232 const unsigned int numTriangles = getNumberOfTriangles();
00233
00234 m_triangleEdge.resize(numTriangles);
00235 for(unsigned int i=0; i<numTriangles; ++i)
00236 {
00237 Triangle &t = m_triangle[i];
00238
00239 for(unsigned int j=0; j<3; ++j)
00240 {
00241 int edgeIndex = getEdgeIndex(t[(j+1)%3],t[(j+2)%3]);
00242 m_triangleEdge[i][j] = edgeIndex;
00243 }
00244 }
00245 }
00246
00247 const sofa::helper::vector<Triangle> & TriangleSetTopologyContainer::getTriangleArray()
00248 {
00249 if(!hasTriangles() && getNbPoints()>0)
00250 {
00251 #ifndef NDEBUG
00252 cout << "[TriangleSetTopologyContainer::getTriangleArray] creating triangle array." << endl;
00253 #endif
00254 createTriangleSetArray();
00255 }
00256
00257 return m_triangle;
00258 }
00259
00260
00261 int TriangleSetTopologyContainer::getTriangleIndex(PointID v1, PointID v2, PointID v3)
00262 {
00263 if(!hasTriangleVertexShell())
00264 createTriangleVertexShellArray();
00265
00266 sofa::helper::vector<unsigned int> set1 = getTriangleVertexShell(v1);
00267 sofa::helper::vector<unsigned int> set2 = getTriangleVertexShell(v2);
00268 sofa::helper::vector<unsigned int> set3 = getTriangleVertexShell(v3);
00269
00270 sort(set1.begin(), set1.end());
00271 sort(set2.begin(), set2.end());
00272 sort(set3.begin(), set3.end());
00273
00274
00275 sofa::helper::vector<unsigned int> out1(set1.size()+set2.size());
00276 sofa::helper::vector<unsigned int>::iterator result1;
00277 result1 = std::set_intersection(set1.begin(),set1.end(),set2.begin(),set2.end(),out1.begin());
00278 out1.erase(result1,out1.end());
00279
00280 sofa::helper::vector<unsigned int> out2(set3.size()+out1.size());
00281 sofa::helper::vector<unsigned int>::iterator result2;
00282 result2 = std::set_intersection(set3.begin(),set3.end(),out1.begin(),out1.end(),out2.begin());
00283 out2.erase(result2,out2.end());
00284
00285 #ifndef NDEBUG
00286 if(out2.size() > 1)
00287 cout << "Warning. [TriangleSetTopologyContainer::getTriangleIndex] more than one triangle found" << endl;
00288 #endif
00289
00290 if (out2.size()==1)
00291 return (int) (out2[0]);
00292 else
00293 return -1;
00294 }
00295
00296 unsigned int TriangleSetTopologyContainer::getNumberOfTriangles() const
00297 {
00298 return m_triangle.size();
00299 }
00300
00301 const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TriangleSetTopologyContainer::getTriangleVertexShellArray()
00302 {
00303 if(!hasTriangleVertexShell())
00304 {
00305 #ifndef NDEBUG
00306 cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShellArray] triangle vertex shell array is empty." << endl;
00307 #endif
00308 createTriangleVertexShellArray();
00309 }
00310
00311 return m_triangleVertexShell;
00312 }
00313
00314 const sofa::helper::vector< sofa::helper::vector<unsigned int> > &TriangleSetTopologyContainer::getTriangleEdgeShellArray()
00315 {
00316 if(!hasTriangleEdgeShell())
00317 {
00318 #ifndef NDEBUG
00319 cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShellArray] triangle edge shell array is empty." << endl;
00320 #endif
00321 createTriangleEdgeShellArray();
00322 }
00323
00324 return m_triangleEdgeShell;
00325 }
00326
00327 const sofa::helper::vector<TriangleEdges> &TriangleSetTopologyContainer::getTriangleEdgeArray()
00328 {
00329 if(m_triangleEdge.empty())
00330 createTriangleEdgeArray();
00331
00332 return m_triangleEdge;
00333 }
00334
00335 const VertexTriangles& TriangleSetTopologyContainer::getTriangleVertexShell(PointID i)
00336 {
00337 if(!hasTriangleVertexShell())
00338 {
00339 #ifndef NDEBUG
00340 cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShell] triangle vertex shell array is empty." << endl;
00341 #endif
00342 createTriangleVertexShellArray();
00343 }
00344 else if( i >= m_triangleVertexShell.size())
00345 {
00346 #ifndef NDEBUG
00347 cout << "Error. [TriangleSetTopologyContainer::getTriangleVertexShell] index out of bounds." << endl;
00348 #endif
00349 createTriangleVertexShellArray();
00350 }
00351
00352 return m_triangleVertexShell[i];
00353 }
00354
00355 const EdgeTriangles& TriangleSetTopologyContainer::getTriangleEdgeShell(EdgeID i)
00356 {
00357 if(!hasTriangleEdgeShell())
00358 {
00359 #ifndef NDEBUG
00360 cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShell] triangle edge shell array is empty." << endl;
00361 #endif
00362 createTriangleEdgeShellArray();
00363 }
00364 else if( i >= m_triangleEdgeShell.size())
00365 {
00366 #ifndef NDEBUG
00367 cout << "Error. [TriangleSetTopologyContainer::getTriangleEdgeShell] index out of bounds." << endl;
00368 #endif
00369 createTriangleEdgeShellArray();
00370 }
00371
00372 return m_triangleEdgeShell[i];
00373 }
00374
00375 const TriangleEdges &TriangleSetTopologyContainer::getTriangleEdge(const unsigned int i)
00376 {
00377 if(m_triangleEdge.empty())
00378 createTriangleEdgeArray();
00379
00380 if( i >= m_triangleEdge.size())
00381 {
00382 #ifndef NDEBUG
00383 cout << "Error. [TriangleSetTopologyContainer::getTriangleEdge] index out of bounds." << endl;
00384 #endif
00385 createTriangleEdgeArray();
00386 }
00387
00388 return m_triangleEdge[i];
00389 }
00390
00391 int TriangleSetTopologyContainer::getVertexIndexInTriangle(const Triangle &t, PointID vertexIndex) const
00392 {
00393 if (t[0]==vertexIndex)
00394 return 0;
00395 else if (t[1]==vertexIndex)
00396 return 1;
00397 else if (t[2]==vertexIndex)
00398 return 2;
00399 else
00400 return -1;
00401 }
00402
00403 int TriangleSetTopologyContainer::getEdgeIndexInTriangle(const TriangleEdges &t, EdgeID edgeIndex) const
00404 {
00405 if (t[0]==edgeIndex)
00406 return 0;
00407 else if (t[1]==edgeIndex)
00408 return 1;
00409 else if (t[2]==edgeIndex)
00410 return 2;
00411 else
00412 return -1;
00413 }
00414
00415 sofa::helper::vector< unsigned int > &TriangleSetTopologyContainer::getTriangleEdgeShellForModification(const unsigned int i)
00416 {
00417 if(!hasTriangleEdgeShell())
00418 {
00419 #ifndef NDEBUG
00420 cout << "Warning. [TriangleSetTopologyContainer::getTriangleEdgeShellForModification] triangle edge shell array is empty." << endl;
00421 #endif
00422 createTriangleEdgeShellArray();
00423 }
00424
00425 if( i >= m_triangleEdgeShell.size())
00426 {
00427 #ifndef NDEBUG
00428 cout << "Error. [TriangleSetTopologyContainer::getTriangleEdgeShellForModification] index out of bounds." << endl;
00429 #endif
00430 createTriangleEdgeShellArray();
00431 }
00432
00433 return m_triangleEdgeShell[i];
00434 }
00435
00436 sofa::helper::vector< unsigned int > &TriangleSetTopologyContainer::getTriangleVertexShellForModification(const unsigned int i)
00437 {
00438 if(!hasTriangleVertexShell())
00439 {
00440 #ifndef NDEBUG
00441 cout << "Warning. [TriangleSetTopologyContainer::getTriangleVertexShellForModification] triangle vertex shell array is empty." << endl;
00442 #endif
00443 createTriangleVertexShellArray();
00444 }
00445
00446 if( i >= m_triangleVertexShell.size())
00447 {
00448 #ifndef NDEBUG
00449 cout << "Error. [TriangleSetTopologyContainer::getTriangleVertexShellForModification] index out of bounds." << endl;
00450 #endif
00451 createTriangleVertexShellArray();
00452 }
00453
00454 return m_triangleVertexShell[i];
00455 }
00456
00457 bool TriangleSetTopologyContainer::checkTopology() const
00458 {
00459 #ifndef NDEBUG
00460 bool ret = true;
00461
00462 if (hasTriangleVertexShell())
00463 {
00464 for (unsigned int i=0; i<m_triangleVertexShell.size(); ++i)
00465 {
00466 const sofa::helper::vector<unsigned int> &tvs = m_triangleVertexShell[i];
00467 for (unsigned int j=0; j<tvs.size(); ++j)
00468 {
00469 bool check_triangle_vertex_shell = (m_triangle[tvs[j]][0]==i)
00470 || (m_triangle[tvs[j]][1]==i)
00471 || (m_triangle[tvs[j]][2]==i);
00472 if(!check_triangle_vertex_shell)
00473 {
00474 std::cout << "*** CHECK FAILED : check_triangle_vertex_shell, i = " << i << " , j = " << j << std::endl;
00475 ret = false;
00476 }
00477 }
00478 }
00479 }
00480
00481 if (hasTriangleEdgeShell())
00482 {
00483 for (unsigned int i=0;i<m_triangleEdgeShell.size();++i)
00484 {
00485 const sofa::helper::vector<unsigned int> &tes=m_triangleEdgeShell[i];
00486 for (unsigned int j=0;j<tes.size();++j)
00487 {
00488 bool check_triangle_edge_shell = (m_triangleEdge[tes[j]][0]==i)
00489 || (m_triangleEdge[tes[j]][1]==i)
00490 || (m_triangleEdge[tes[j]][2]==i);
00491 if(!check_triangle_edge_shell)
00492 {
00493 std::cout << "*** CHECK FAILED : check_triangle_edge_shell, i = " << i << " , j = " << j << std::endl;
00494 ret = false;
00495 }
00496 }
00497 }
00498 }
00499
00500 return ret && EdgeSetTopologyContainer::checkTopology();
00501 #else
00502 return true;
00503 #endif
00504 }
00505
00506 bool TriangleSetTopologyContainer::hasTriangles() const
00507 {
00508 return !m_triangle.empty();
00509 }
00510
00511 bool TriangleSetTopologyContainer::hasTriangleEdges() const
00512 {
00513 return !m_triangleEdge.empty();
00514 }
00515
00516 bool TriangleSetTopologyContainer::hasTriangleVertexShell() const
00517 {
00518 return !m_triangleVertexShell.empty();
00519 }
00520
00521 bool TriangleSetTopologyContainer::hasTriangleEdgeShell() const
00522 {
00523 return !m_triangleEdgeShell.empty();
00524 }
00525
00526 void TriangleSetTopologyContainer::clearTriangleVertexShell()
00527 {
00528 for(unsigned int i=0; i<m_triangleVertexShell.size(); ++i)
00529 m_triangleVertexShell[i].clear();
00530
00531 m_triangleVertexShell.clear();
00532 }
00533
00534 void TriangleSetTopologyContainer::clearTriangleEdgeShell()
00535 {
00536 for(unsigned int i=0; i<m_triangleEdgeShell.size(); ++i)
00537 m_triangleEdgeShell[i].clear();
00538
00539 m_triangleEdgeShell.clear();
00540 }
00541
00542 void TriangleSetTopologyContainer::clearTriangleEdges()
00543 {
00544 m_triangleEdge.clear();
00545 }
00546
00547 void TriangleSetTopologyContainer::clearTriangles()
00548 {
00549 m_triangle.clear();
00550 }
00551
00552 void TriangleSetTopologyContainer::clear()
00553 {
00554 clearTriangleVertexShell();
00555 clearTriangleEdgeShell();
00556 clearTriangleEdges();
00557 clearTriangles();
00558 EdgeSetTopologyContainer::clear();
00559 }
00560
00561 void snapping_test_triangle(double epsilon, double alpha0, double alpha1, double alpha2,
00562 bool& is_snap_0, bool& is_snap_1, bool& is_snap_2)
00563 {
00564 is_snap_0=false;
00565 is_snap_1=false;
00566 is_snap_2=false;
00567
00568 if(alpha0>=alpha1 && alpha0>=alpha2)
00569 {
00570 is_snap_0=(alpha1+alpha2<epsilon);
00571 }
00572 else
00573 {
00574 if(alpha1>=alpha0 && alpha1>=alpha2)
00575 {
00576 is_snap_1=(alpha0+alpha2<epsilon);
00577 }
00578 else
00579 {
00580 is_snap_2=(alpha0+alpha1<epsilon);
00581 }
00582 }
00583 }
00584
00585 void snapping_test_edge(double epsilon, double alpha0, double alpha1,
00586 bool& is_snap_0, bool& is_snap_1)
00587 {
00588 is_snap_0=false;
00589 is_snap_1=false;
00590
00591 if(alpha0>=alpha1)
00592 {
00593 is_snap_0=(alpha1<epsilon);
00594 }
00595 else
00596 {
00597 is_snap_1=(alpha0<epsilon);
00598 }
00599 }
00600
00601 }
00602
00603 }
00604
00605 }