extract_manifold_patches.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
  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 "extract_manifold_patches.h"
  9. #include "unique_edge_map.h"
  10. #include <cassert>
  11. #include <limits>
  12. #include <queue>
  13. template<
  14. typename DerivedF,
  15. typename DerivedEMAP,
  16. typename uE2EType,
  17. typename DerivedP>
  18. IGL_INLINE size_t igl::extract_manifold_patches(
  19. const Eigen::PlainObjectBase<DerivedF>& F,
  20. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  21. const std::vector<std::vector<uE2EType> >& uE2E,
  22. Eigen::PlainObjectBase<DerivedP>& P)
  23. {
  24. assert(F.cols() == 3);
  25. const size_t num_faces = F.rows();
  26. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  27. auto face_and_corner_index_to_edge_index = [&](size_t fi, size_t ci) {
  28. return ci*num_faces + fi;
  29. };
  30. auto is_manifold_edge = [&](size_t fi, size_t ci) -> bool {
  31. const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
  32. return uE2E[EMAP(ei, 0)].size() == 2;
  33. };
  34. auto get_adj_face_index = [&](size_t fi, size_t ci) -> size_t {
  35. const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
  36. const auto& adj_faces = uE2E[EMAP(ei, 0)];
  37. assert(adj_faces.size() == 2);
  38. if (adj_faces[0] == ei) {
  39. return edge_index_to_face_index(adj_faces[1]);
  40. } else {
  41. assert(adj_faces[1] == ei);
  42. return edge_index_to_face_index(adj_faces[0]);
  43. }
  44. };
  45. typedef typename DerivedP::Scalar Scalar;
  46. const Scalar INVALID = std::numeric_limits<Scalar>::max();
  47. P.resize(num_faces,1);
  48. P.setConstant(INVALID);
  49. size_t num_patches = 0;
  50. for (size_t i=0; i<num_faces; i++) {
  51. if (P(i,0) != INVALID) continue;
  52. std::queue<size_t> Q;
  53. Q.push(i);
  54. P(i,0) = num_patches;
  55. while (!Q.empty()) {
  56. const size_t fid = Q.front();
  57. Q.pop();
  58. for (size_t j=0; j<3; j++) {
  59. if (is_manifold_edge(fid, j)) {
  60. const size_t adj_fid = get_adj_face_index(fid, j);
  61. if (P(adj_fid,0) == INVALID) {
  62. Q.push(adj_fid);
  63. P(adj_fid,0) = num_patches;
  64. }
  65. }
  66. }
  67. }
  68. num_patches++;
  69. }
  70. assert((P.array() != INVALID).all());
  71. return num_patches;
  72. }
  73. template<
  74. typename DerivedF,
  75. typename DerivedP>
  76. IGL_INLINE size_t igl::extract_manifold_patches(
  77. const Eigen::PlainObjectBase<DerivedF>& F,
  78. Eigen::PlainObjectBase<DerivedP>& P)
  79. {
  80. Eigen::MatrixXi E, uE;
  81. Eigen::VectorXi EMAP;
  82. std::vector<std::vector<size_t> > uE2E;
  83. igl::unique_edge_map(F, E, uE, EMAP, uE2E);
  84. return igl::extract_manifold_patches(F, EMAP, uE2E, P);
  85. }
  86. #ifdef IGL_STATIC_LIBRARY
  87. // Explicit template instantiation
  88. // generated by autoexplicit.sh
  89. template unsigned long igl::extract_manifold_patches<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> >&);
  90. template size_t 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> >&);
  91. template unsigned long igl::extract_manifold_patches<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > 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> >&);
  92. #ifdef WIN32
  93. template unsigned __int64 igl::extract_manifold_patches<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned __int64, class Eigen::Matrix<int, -1, 1, 0, -1, 1>>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
  94. template unsigned __int64 igl::extract_manifold_patches<class Eigen::Matrix<int, -1, 3, 1, -1, 3>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned __int64, class Eigen::Matrix<int, -1, 1, 0, -1, 1>>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 3, 1, -1, 3>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> &);
  95. #endif
  96. #endif