is_vertex_manifold.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "is_vertex_manifold.h"
  9. #include "triangle_triangle_adjacency.h"
  10. #include "vertex_triangle_adjacency.h"
  11. #include "unique.h"
  12. #include <vector>
  13. #include <cassert>
  14. #include <map>
  15. #include <queue>
  16. #include <iostream>
  17. template <typename DerivedF,typename DerivedB>
  18. IGL_INLINE bool igl::is_vertex_manifold(
  19. const Eigen::MatrixBase<DerivedF>& F,
  20. Eigen::PlainObjectBase<DerivedB>& B)
  21. {
  22. assert(F.cols() == 3 && "F must contain triangles");
  23. typedef typename DerivedF::Scalar Index;
  24. using FIndex = int;
  25. const Index n = F.maxCoeff()+1;
  26. std::vector<std::vector<std::vector<FIndex > > > TT;
  27. std::vector<std::vector<std::vector<FIndex > > > TTi;
  28. triangle_triangle_adjacency(F,TT,TTi);
  29. std::vector<std::vector<FIndex > > V2F,_1;
  30. vertex_triangle_adjacency(n,F,V2F,_1);
  31. const auto & check_vertex = [&](const Index v)->bool
  32. {
  33. std::vector<FIndex> uV2Fv;
  34. {
  35. std::vector<size_t> _1,_2;
  36. unique(V2F[v],uV2Fv,_1,_2);
  37. }
  38. const FIndex one_ring_size = uV2Fv.size();
  39. if(one_ring_size == 0)
  40. {
  41. return false;
  42. }
  43. const FIndex g = uV2Fv[0];
  44. std::queue<Index> Q;
  45. Q.push(g);
  46. std::map<FIndex,bool> seen;
  47. while(!Q.empty())
  48. {
  49. const FIndex f = Q.front();
  50. Q.pop();
  51. if(seen.count(f)==1)
  52. {
  53. continue;
  54. }
  55. seen[f] = true;
  56. // Face f's neighbor lists opposite opposite each corner
  57. for(const auto & c : TT[f])
  58. {
  59. // Each neighbor
  60. for(const auto & n : c)
  61. {
  62. bool contains_v = false;
  63. for(Index nc = 0;nc<F.cols();nc++)
  64. {
  65. if(F(n,nc) == v)
  66. {
  67. contains_v = true;
  68. break;
  69. }
  70. }
  71. if(seen.count(n)==0 && contains_v)
  72. {
  73. Q.push(n);
  74. }
  75. }
  76. }
  77. }
  78. return one_ring_size == (FIndex) seen.size();
  79. };
  80. // Unreferenced vertices are considered non-manifold
  81. B.setConstant(n,1,false);
  82. // Loop over all vertices touched by F
  83. bool all = true;
  84. for(Index v = 0;v<n;v++)
  85. {
  86. all &= B(v) = check_vertex(v);
  87. }
  88. return all;
  89. }
  90. template <typename DerivedF>
  91. IGL_INLINE bool igl::is_vertex_manifold(
  92. const Eigen::MatrixBase<DerivedF>& F)
  93. {
  94. Eigen::Array<bool,Eigen::Dynamic,1> B;
  95. return is_vertex_manifold(F,B);
  96. }
  97. #ifdef IGL_STATIC_LIBRARY
  98. template bool igl::is_vertex_manifold<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >( Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  99. template bool igl::is_vertex_manifold<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  100. template bool igl::is_vertex_manifold<Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&);
  101. #endif