extract_manifold_patches.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include "extract_manifold_patches.h"
  2. #include "unique_edge_map.h"
  3. #include <cassert>
  4. #include <limits>
  5. #include <queue>
  6. template<
  7. typename DerivedF,
  8. typename DerivedEMAP,
  9. typename uE2EType,
  10. typename DerivedP>
  11. IGL_INLINE size_t igl::extract_manifold_patches(
  12. const Eigen::PlainObjectBase<DerivedF>& F,
  13. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  14. const std::vector<std::vector<uE2EType> >& uE2E,
  15. Eigen::PlainObjectBase<DerivedP>& P)
  16. {
  17. assert(F.cols() == 3);
  18. const size_t num_faces = F.rows();
  19. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  20. auto face_and_corner_index_to_edge_index = [&](size_t fi, size_t ci) {
  21. return ci*num_faces + fi;
  22. };
  23. auto is_manifold_edge = [&](size_t fi, size_t ci) -> bool {
  24. const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
  25. return uE2E[EMAP(ei, 0)].size() == 2;
  26. };
  27. auto get_adj_face_index = [&](size_t fi, size_t ci) -> size_t {
  28. const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
  29. const auto& adj_faces = uE2E[EMAP(ei, 0)];
  30. assert(adj_faces.size() == 2);
  31. if (adj_faces[0] == ei) {
  32. return edge_index_to_face_index(adj_faces[1]);
  33. } else {
  34. assert(adj_faces[1] == ei);
  35. return edge_index_to_face_index(adj_faces[0]);
  36. }
  37. };
  38. typedef typename DerivedP::Scalar Scalar;
  39. const Scalar INVALID = std::numeric_limits<Scalar>::max();
  40. P.resize(num_faces,1);
  41. P.setConstant(INVALID);
  42. size_t num_patches = 0;
  43. for (size_t i=0; i<num_faces; i++) {
  44. if (P(i,0) != INVALID) continue;
  45. std::queue<size_t> Q;
  46. Q.push(i);
  47. P(i,0) = num_patches;
  48. while (!Q.empty()) {
  49. const size_t fid = Q.front();
  50. Q.pop();
  51. for (size_t j=0; j<3; j++) {
  52. if (is_manifold_edge(fid, j)) {
  53. const size_t adj_fid = get_adj_face_index(fid, j);
  54. if (P(adj_fid,0) == INVALID) {
  55. Q.push(adj_fid);
  56. P(adj_fid,0) = num_patches;
  57. }
  58. }
  59. }
  60. }
  61. num_patches++;
  62. }
  63. assert((P.array() != INVALID).all());
  64. return num_patches;
  65. }
  66. template<
  67. typename DerivedF,
  68. typename DerivedP>
  69. IGL_INLINE size_t igl::extract_manifold_patches(
  70. const Eigen::PlainObjectBase<DerivedF>& F,
  71. Eigen::PlainObjectBase<DerivedP>& P)
  72. {
  73. Eigen::MatrixXi E, uE;
  74. Eigen::VectorXi EMAP;
  75. std::vector<std::vector<size_t> > uE2E;
  76. igl::unique_edge_map(F, E, uE, EMAP, uE2E);
  77. return igl::extract_manifold_patches(F, EMAP, uE2E, P);
  78. }
  79. #ifdef IGL_STATIC_LIBRARY
  80. template unsigned long igl::extract_manifold_patches<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long, 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> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  81. #endif