boundary_facets.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 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 "boundary_facets.h"
  9. #include "face_occurrences.h"
  10. #include "list_to_matrix.h"
  11. #include "matrix_to_list.h"
  12. #include "sort.h"
  13. #include "unique_rows.h"
  14. #include "accumarray.h"
  15. #include "slice_mask.h"
  16. #include <Eigen/Core>
  17. #include <map>
  18. #include <iostream>
  19. template <
  20. typename DerivedT,
  21. typename DerivedF,
  22. typename DerivedJ,
  23. typename DerivedK>
  24. IGL_INLINE void igl::boundary_facets(
  25. const Eigen::MatrixBase<DerivedT>& T,
  26. Eigen::PlainObjectBase<DerivedF>& F,
  27. Eigen::PlainObjectBase<DerivedJ>& J,
  28. Eigen::PlainObjectBase<DerivedK>& K)
  29. {
  30. const int simplex_size = T.cols();
  31. // Handle boring base case
  32. if(T.rows() == 0)
  33. {
  34. F.resize(0,simplex_size-1);
  35. J.resize(0,1);
  36. K.resize(0,1);
  37. return;
  38. }
  39. // Get a list of all facets
  40. DerivedF allF(T.rows()*simplex_size,simplex_size-1);
  41. // Gather faces (e.g., loop over tets)
  42. for(int i = 0; i< (int)T.rows();i++)
  43. {
  44. switch(simplex_size)
  45. {
  46. case 4:
  47. // get face in correct order
  48. allF(i*simplex_size+0,0) = T(i,1);
  49. allF(i*simplex_size+0,1) = T(i,3);
  50. allF(i*simplex_size+0,2) = T(i,2);
  51. // get face in correct order
  52. allF(i*simplex_size+1,0) = T(i,0);
  53. allF(i*simplex_size+1,1) = T(i,2);
  54. allF(i*simplex_size+1,2) = T(i,3);
  55. // get face in correct order
  56. allF(i*simplex_size+2,0) = T(i,0);
  57. allF(i*simplex_size+2,1) = T(i,3);
  58. allF(i*simplex_size+2,2) = T(i,1);
  59. // get face in correct order
  60. allF(i*simplex_size+3,0) = T(i,0);
  61. allF(i*simplex_size+3,1) = T(i,1);
  62. allF(i*simplex_size+3,2) = T(i,2);
  63. break;
  64. case 3:
  65. allF(i*simplex_size+0,0) = T(i,1);
  66. allF(i*simplex_size+0,1) = T(i,2);
  67. allF(i*simplex_size+1,0) = T(i,2);
  68. allF(i*simplex_size+1,1) = T(i,0);
  69. allF(i*simplex_size+2,0) = T(i,0);
  70. allF(i*simplex_size+2,1) = T(i,1);
  71. break;
  72. }
  73. }
  74. DerivedF sortedF;
  75. igl::sort(allF,2,true,sortedF);
  76. Eigen::VectorXi m,n;
  77. {
  78. DerivedF _1;
  79. igl::unique_rows(sortedF,_1,m,n);
  80. }
  81. Eigen::VectorXi C;
  82. igl::accumarray(n,1,C);
  83. const int ones = (C.array()==1).count();
  84. // Resize output to fit number of non-twos
  85. F.resize(ones, allF.cols());
  86. J.resize(F.rows(),1);
  87. K.resize(F.rows(),1);
  88. int k = 0;
  89. for(int c = 0;c< (int)C.size();c++)
  90. {
  91. if(C(c) == 1)
  92. {
  93. const int i = m(c);
  94. assert(k<(int)F.rows());
  95. F.row(k) = allF.row(i);
  96. J(k) = i/simplex_size;
  97. K(k) = i%simplex_size;
  98. k++;
  99. }
  100. }
  101. assert(k==(int)F.rows());
  102. }
  103. template <typename DerivedT, typename DerivedF>
  104. IGL_INLINE void igl::boundary_facets(
  105. const Eigen::MatrixBase<DerivedT>& T,
  106. Eigen::PlainObjectBase<DerivedF>& F)
  107. {
  108. Eigen::VectorXi J,K;
  109. return boundary_facets(T,F,J,K);
  110. }
  111. template <typename DerivedT, typename Ret>
  112. Ret igl::boundary_facets(
  113. const Eigen::MatrixBase<DerivedT>& T)
  114. {
  115. Ret F;
  116. igl::boundary_facets(T,F);
  117. return F;
  118. }
  119. template <typename IntegerT, typename IntegerF>
  120. IGL_INLINE void igl::boundary_facets(
  121. const std::vector<std::vector<IntegerT> > & T,
  122. std::vector<std::vector<IntegerF> > & F)
  123. {
  124. // Kept for legacy reasons. Could probably just delete.
  125. using namespace std;
  126. if(T.size() == 0)
  127. {
  128. F.clear();
  129. return;
  130. }
  131. int simplex_size = T[0].size();
  132. // Get a list of all faces
  133. vector<vector<IntegerF> > allF(
  134. T.size()*simplex_size,
  135. vector<IntegerF>(simplex_size-1));
  136. // Gather faces, loop over tets
  137. for(int i = 0; i< (int)T.size();i++)
  138. {
  139. assert((int)T[i].size() == simplex_size);
  140. switch(simplex_size)
  141. {
  142. case 4:
  143. // get face in correct order
  144. allF[i*simplex_size+0][0] = T[i][1];
  145. allF[i*simplex_size+0][1] = T[i][3];
  146. allF[i*simplex_size+0][2] = T[i][2];
  147. // get face in correct order
  148. allF[i*simplex_size+1][0] = T[i][0];
  149. allF[i*simplex_size+1][1] = T[i][2];
  150. allF[i*simplex_size+1][2] = T[i][3];
  151. // get face in correct order
  152. allF[i*simplex_size+2][0] = T[i][0];
  153. allF[i*simplex_size+2][1] = T[i][3];
  154. allF[i*simplex_size+2][2] = T[i][1];
  155. // get face in correct order
  156. allF[i*simplex_size+3][0] = T[i][0];
  157. allF[i*simplex_size+3][1] = T[i][1];
  158. allF[i*simplex_size+3][2] = T[i][2];
  159. break;
  160. case 3:
  161. allF[i*simplex_size+0][0] = T[i][1];
  162. allF[i*simplex_size+0][1] = T[i][2];
  163. allF[i*simplex_size+1][0] = T[i][2];
  164. allF[i*simplex_size+1][1] = T[i][0];
  165. allF[i*simplex_size+2][0] = T[i][0];
  166. allF[i*simplex_size+2][1] = T[i][1];
  167. break;
  168. }
  169. }
  170. // Counts
  171. vector<int> C;
  172. face_occurrences(allF,C);
  173. // Q: Why not just count the number of ones?
  174. // A: because we are including non-manifold edges as boundary edges
  175. int twos = (int) count(C.begin(),C.end(),2);
  176. //int ones = (int) count(C.begin(),C.end(),1);
  177. // Resize output to fit number of ones
  178. F.resize(allF.size() - twos);
  179. //F.resize(ones);
  180. int k = 0;
  181. for(int i = 0;i< (int)allF.size();i++)
  182. {
  183. if(C[i] != 2)
  184. {
  185. assert(k<(int)F.size());
  186. F[k] = allF[i];
  187. k++;
  188. }
  189. }
  190. assert(k==(int)F.size());
  191. //if(k != F.size())
  192. //{
  193. // printf("%d =? %d\n",k,F.size());
  194. //}
  195. }
  196. #ifdef IGL_STATIC_LIBRARY
  197. // Explicit template instantiation
  198. // generated by autoexplicit.sh
  199. template void igl::boundary_facets<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> >&);
  200. // generated by autoexplicit.sh
  201. template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
  202. // generated by autoexplicit.sh
  203. template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  204. template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
  205. //template Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
  206. template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<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&);
  207. template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  208. #endif