extract_manifold_patches.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 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 "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 DeriveduEC,
  17. typename DeriveduEE,
  18. typename DerivedP>
  19. IGL_INLINE int igl::extract_manifold_patches(
  20. const Eigen::MatrixBase<DerivedF>& F,
  21. const Eigen::MatrixBase<DerivedEMAP>& EMAP,
  22. const Eigen::MatrixBase<DeriveduEC>& uEC,
  23. const Eigen::MatrixBase<DeriveduEE>& uEE,
  24. Eigen::PlainObjectBase<DerivedP>& P)
  25. {
  26. assert(F.cols() == 3);
  27. const int num_faces = F.rows();
  28. // given directed edge index return corresponding face index
  29. auto e2f = [&](int ei) { return ei % num_faces; };
  30. // given face index and corner given index of opposite directed edge
  31. auto fc2e = [&](int fi, int ci) { return ci*num_faces + fi; };
  32. // given face index and corner return whether unique edge has incidence == 2
  33. auto is_manifold_edge = [&](int fi, int ci) -> bool
  34. {
  35. const int ei = fc2e(fi, ci);
  36. const int u = EMAP(ei);
  37. //return uE2E[EMAP(ei)].size() == 2;
  38. return (uEC(u+1)-uEC(u))==2;
  39. };
  40. // given face and corner index return adjacent face index (assumes manifold)
  41. auto fc2a = [&](int fi, int ci) -> int
  42. {
  43. const int ei = fc2e(fi, ci);
  44. const int u = EMAP(ei);
  45. //const auto& adj_faces = uE2E[EMAP(ei)];
  46. //assert(adj_faces.size() == 2);
  47. assert(uEC(u+1)-uEC(u) == 2);
  48. //if (adj_faces[0] == ei)
  49. //{
  50. // return e2f(adj_faces[1]);
  51. //} else
  52. //{
  53. // assert(adj_faces[1] == ei);
  54. // return e2f(adj_faces[0]);
  55. //}
  56. return e2f(uEE(uEC(u)) == ei ? uEE(uEC(u)+1) : uEE(uEC(u)));
  57. };
  58. typedef typename DerivedP::Scalar Scalar;
  59. const Scalar INVALID = std::numeric_limits<Scalar>::max();
  60. P.resize(num_faces,1);
  61. P.setConstant(INVALID);
  62. int num_patches = 0;
  63. for (int i=0; i<num_faces; i++)
  64. {
  65. if (P(i,0) != INVALID) continue;
  66. std::queue<int> Q;
  67. Q.push(i);
  68. P(i,0) = num_patches;
  69. while (!Q.empty())
  70. {
  71. const int fid = Q.front();
  72. Q.pop();
  73. for (int j=0; j<3; j++)
  74. {
  75. if (is_manifold_edge(fid, j))
  76. {
  77. const int adj_fid = fc2a(fid, j);
  78. if (P(adj_fid,0) == INVALID)
  79. {
  80. Q.push(adj_fid);
  81. P(adj_fid,0) = num_patches;
  82. }
  83. }
  84. }
  85. }
  86. num_patches++;
  87. }
  88. assert((P.array() != INVALID).all());
  89. return num_patches;
  90. }
  91. template<
  92. typename DerivedF,
  93. typename DerivedEMAP,
  94. typename uE2EType,
  95. typename DerivedP>
  96. IGL_INLINE int igl::extract_manifold_patches(
  97. const Eigen::MatrixBase<DerivedF>& F,
  98. const Eigen::MatrixBase<DerivedEMAP>& EMAP,
  99. const std::vector<std::vector<uE2EType> >& uE2E,
  100. Eigen::PlainObjectBase<DerivedP>& P)
  101. {
  102. assert(F.cols() == 3);
  103. const int num_faces = F.rows();
  104. auto edge_index_to_face_index = [&](int ei) { return ei % num_faces; };
  105. auto face_and_corner_index_to_edge_index = [&](int fi, int ci) {
  106. return ci*num_faces + fi;
  107. };
  108. auto is_manifold_edge = [&](int fi, int ci) -> bool {
  109. const int ei = face_and_corner_index_to_edge_index(fi, ci);
  110. return uE2E[EMAP(ei, 0)].size() == 2;
  111. };
  112. auto get_adj_face_index = [&](int fi, int ci) -> int {
  113. const int ei = face_and_corner_index_to_edge_index(fi, ci);
  114. const auto& adj_faces = uE2E[EMAP(ei, 0)];
  115. assert(adj_faces.size() == 2);
  116. if (adj_faces[0] == ei) {
  117. return edge_index_to_face_index(adj_faces[1]);
  118. } else {
  119. assert(adj_faces[1] == ei);
  120. return edge_index_to_face_index(adj_faces[0]);
  121. }
  122. };
  123. typedef typename DerivedP::Scalar Scalar;
  124. const Scalar INVALID = std::numeric_limits<Scalar>::max();
  125. P.resize(num_faces,1);
  126. P.setConstant(INVALID);
  127. int num_patches = 0;
  128. for (int i=0; i<num_faces; i++) {
  129. if (P(i,0) != INVALID) continue;
  130. std::queue<int> Q;
  131. Q.push(i);
  132. P(i,0) = num_patches;
  133. while (!Q.empty()) {
  134. const int fid = Q.front();
  135. Q.pop();
  136. for (int j=0; j<3; j++) {
  137. if (is_manifold_edge(fid, j)) {
  138. const int adj_fid = get_adj_face_index(fid, j);
  139. if (P(adj_fid,0) == INVALID) {
  140. Q.push(adj_fid);
  141. P(adj_fid,0) = num_patches;
  142. }
  143. }
  144. }
  145. }
  146. num_patches++;
  147. }
  148. assert((P.array() != INVALID).all());
  149. return num_patches;
  150. }
  151. template <
  152. typename DerivedF,
  153. typename DerivedP>
  154. IGL_INLINE int igl::extract_manifold_patches(
  155. const Eigen::MatrixBase<DerivedF> &F,
  156. Eigen::PlainObjectBase<DerivedP> &P)
  157. {
  158. Eigen::MatrixXi E, uE;
  159. Eigen::VectorXi EMAP;
  160. std::vector<std::vector<int> > uE2E;
  161. igl::unique_edge_map(F, E, uE, EMAP, uE2E);
  162. return igl::extract_manifold_patches(F, EMAP, uE2E, P);
  163. }
  164. #ifdef IGL_STATIC_LIBRARY
  165. // Explicit template instantiation
  166. // generated by autoexplicit.sh
  167. template int igl::extract_manifold_patches<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, 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::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  168. template int igl::extract_manifold_patches<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> >&);
  169. template int 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::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<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> >&);
  170. template int 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::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<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> >&);
  171. #endif