boundary_facets.cpp 7.2 KB

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