is_vertex_manifold.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include "is_vertex_manifold.h"
  2. #include "triangle_triangle_adjacency.h"
  3. #include "vertex_triangle_adjacency.h"
  4. #include "unique.h"
  5. #include <vector>
  6. #include <cassert>
  7. #include <map>
  8. #include <queue>
  9. #include <iostream>
  10. template <typename DerivedF,typename DerivedB>
  11. IGL_INLINE bool igl::is_vertex_manifold(
  12. const Eigen::PlainObjectBase<DerivedF>& F,
  13. Eigen::PlainObjectBase<DerivedB>& B)
  14. {
  15. using namespace std;
  16. using namespace Eigen;
  17. assert(F.cols() == 3 && "F must contain triangles");
  18. typedef typename DerivedF::Scalar Index;
  19. typedef typename DerivedF::Index FIndex;
  20. const FIndex m = F.rows();
  21. const Index n = F.maxCoeff()+1;
  22. vector<vector<vector<FIndex > > > TT;
  23. vector<vector<vector<FIndex > > > TTi;
  24. triangle_triangle_adjacency(F,TT,TTi);
  25. vector<vector<FIndex > > V2F,_1;
  26. vertex_triangle_adjacency(n,F,V2F,_1);
  27. const auto & check_vertex = [&](const Index v)->bool
  28. {
  29. vector<FIndex> uV2Fv;
  30. {
  31. vector<size_t> _1,_2;
  32. unique(V2F[v],uV2Fv,_1,_2);
  33. }
  34. const FIndex one_ring_size = uV2Fv.size();
  35. if(one_ring_size == 0)
  36. {
  37. return false;
  38. }
  39. const FIndex g = uV2Fv[0];
  40. queue<Index> Q;
  41. Q.push(g);
  42. map<FIndex,bool> seen;
  43. while(!Q.empty())
  44. {
  45. const FIndex f = Q.front();
  46. Q.pop();
  47. if(seen.count(f)==1)
  48. {
  49. continue;
  50. }
  51. seen[f] = true;
  52. // Face f's neighbor lists opposite opposite each corner
  53. for(const auto & c : TT[f])
  54. {
  55. // Each neighbor
  56. for(const auto & n : c)
  57. {
  58. bool contains_v = false;
  59. for(Index nc = 0;nc<F.cols();nc++)
  60. {
  61. if(F(n,nc) == v)
  62. {
  63. contains_v = true;
  64. break;
  65. }
  66. }
  67. if(seen.count(n)==0 && contains_v)
  68. {
  69. Q.push(n);
  70. }
  71. }
  72. }
  73. }
  74. return one_ring_size == (FIndex) seen.size();
  75. };
  76. // Unreferenced vertices are considered non-manifold
  77. B.setConstant(n,1,false);
  78. // Loop over all vertices touched by F
  79. bool all = true;
  80. for(Index v = 0;v<n;v++)
  81. {
  82. all &= B(v) = check_vertex(v);
  83. }
  84. return all;
  85. }
  86. #ifdef IGL_STATIC_LIBRARY
  87. template bool igl::is_vertex_manifold<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  88. #endif