boundary_facets.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 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 "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 <Eigen/Core>
  16. #include <map>
  17. #include <iostream>
  18. template <
  19. typename DerivedT,
  20. typename DerivedF,
  21. typename DerivedJ,
  22. typename DerivedK>
  23. IGL_INLINE void igl::boundary_facets(
  24. const Eigen::MatrixBase<DerivedT>& T,
  25. Eigen::PlainObjectBase<DerivedF>& F,
  26. Eigen::PlainObjectBase<DerivedJ>& J,
  27. Eigen::PlainObjectBase<DerivedK>& K)
  28. {
  29. const int simplex_size = T.cols();
  30. // Handle boring base case
  31. if(T.rows() == 0)
  32. {
  33. F.resize(0,simplex_size-1);
  34. J.resize(0,1);
  35. K.resize(0,1);
  36. return;
  37. }
  38. // Get a list of all facets/edges
  39. DerivedF allF(T.rows()*simplex_size,simplex_size-1);
  40. switch(simplex_size)
  41. {
  42. case 4:
  43. // Gather faces (e.g., loop over tets)
  44. for(int i = 0; i< (int)T.rows();i++)
  45. {
  46. // get face in correct order
  47. allF(i*simplex_size+0,2) = T(i,1);
  48. allF(i*simplex_size+0,1) = T(i,3);
  49. allF(i*simplex_size+0,0) = T(i,2);
  50. // get face in correct order
  51. allF(i*simplex_size+1,2) = T(i,0);
  52. allF(i*simplex_size+1,1) = T(i,2);
  53. allF(i*simplex_size+1,0) = T(i,3);
  54. // get face in correct order
  55. allF(i*simplex_size+2,2) = T(i,0);
  56. allF(i*simplex_size+2,1) = T(i,3);
  57. allF(i*simplex_size+2,0) = T(i,1);
  58. // get face in correct order
  59. allF(i*simplex_size+3,2) = T(i,0);
  60. allF(i*simplex_size+3,1) = T(i,1);
  61. allF(i*simplex_size+3,0) = T(i,2);
  62. }
  63. break;
  64. case 3:
  65. // Gather edges (loop over triangles)
  66. for(int i = 0; i< (int)T.rows();i++)
  67. {
  68. allF(i*simplex_size+0,0) = T(i,1);
  69. allF(i*simplex_size+0,1) = T(i,2);
  70. allF(i*simplex_size+1,0) = T(i,2);
  71. allF(i*simplex_size+1,1) = T(i,0);
  72. allF(i*simplex_size+2,0) = T(i,0);
  73. allF(i*simplex_size+2,1) = T(i,1);
  74. }
  75. }
  76. DerivedF sortedF;
  77. igl::sort(allF,2,true,sortedF);
  78. Eigen::VectorXi m,n;
  79. {
  80. DerivedF _1;
  81. igl::unique_rows(sortedF,_1,m,n);
  82. }
  83. Eigen::VectorXi C;
  84. igl::accumarray(n,1,C);
  85. const int ones = (C.array()==1).count();
  86. // Resize output to fit number of non-twos
  87. F.resize(ones, allF.cols());
  88. J.resize(F.rows(),1);
  89. K.resize(F.rows(),1);
  90. int k = 0;
  91. for(int c = 0;c< (int)C.size();c++)
  92. {
  93. if(C(c) == 1)
  94. {
  95. const int i = m(c);
  96. assert(k<(int)F.rows());
  97. F.row(k) = allF.row(i);
  98. J(k) = i/simplex_size;
  99. K(k) = i%simplex_size;
  100. k++;
  101. }
  102. }
  103. assert(k==(int)F.rows());
  104. }
  105. template <typename DerivedT, typename DerivedF>
  106. IGL_INLINE void igl::boundary_facets(
  107. const Eigen::MatrixBase<DerivedT>& T,
  108. Eigen::PlainObjectBase<DerivedF>& F)
  109. {
  110. Eigen::VectorXi J,K;
  111. return boundary_facets(T,F,J,K);
  112. }
  113. template <typename DerivedT, typename Ret>
  114. Ret igl::boundary_facets(
  115. const Eigen::MatrixBase<DerivedT>& T)
  116. {
  117. Ret F;
  118. igl::boundary_facets(T,F);
  119. return F;
  120. }
  121. #ifdef IGL_STATIC_LIBRARY
  122. // Explicit template instantiation
  123. 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> >&);
  124. 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> >&);
  125. 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> >&);
  126. 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&);
  127. 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> >&);
  128. #endif