slice_tets.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "slice_tets.h"
  2. #include <igl/sort.h>
  3. #include <igl/cat.h>
  4. #include <igl/per_face_normals.h>
  5. #include <cassert>
  6. #include <algorithm>
  7. #include <vector>
  8. template <
  9. typename DerivedV,
  10. typename DerivedT,
  11. typename Derivedplane,
  12. typename DerivedU,
  13. typename DerivedG,
  14. typename DerivedJ,
  15. typename BCType>
  16. IGL_INLINE void igl::slice_tets(
  17. const Eigen::PlainObjectBase<DerivedV>& V,
  18. const Eigen::PlainObjectBase<DerivedT>& T,
  19. const Eigen::PlainObjectBase<Derivedplane> & plane,
  20. Eigen::PlainObjectBase<DerivedU>& U,
  21. Eigen::PlainObjectBase<DerivedG>& G,
  22. Eigen::PlainObjectBase<DerivedJ>& J,
  23. Eigen::SparseMatrix<BCType> & BC)
  24. {
  25. using namespace Eigen;
  26. using namespace std;
  27. assert(V.cols() == 3 && "V should be #V by 3");
  28. assert(T.cols() == 4 && "T should be #T by 4");
  29. assert(plane.size() == 4 && "Plane equation should be 4 coefficients");
  30. // number of tets
  31. const size_t m = T.rows();
  32. typedef typename DerivedV::Scalar Scalar;
  33. typedef typename DerivedT::Scalar Index;
  34. typedef Matrix<Scalar,Dynamic,1> VectorXS;
  35. typedef Matrix<Scalar,Dynamic,4> MatrixX4S;
  36. typedef Matrix<Scalar,Dynamic,3> MatrixX3S;
  37. typedef Matrix<Scalar,Dynamic,2> MatrixX2S;
  38. typedef Matrix<Index,Dynamic,4> MatrixX4I;
  39. typedef Matrix<Index,Dynamic,3> MatrixX3I;
  40. typedef Matrix<Index,Dynamic,1> VectorXI;
  41. typedef Matrix<bool,Dynamic,1> VectorXb;
  42. // Value of plane's implicit function at all vertices
  43. VectorXS IV =
  44. (V.col(0)*plane(0) +
  45. V.col(1)*plane(1) +
  46. V.col(2)*plane(2)).array()
  47. + plane(3);
  48. MatrixX4S IT(m,4);
  49. for(size_t t = 0;t<m;t++)
  50. {
  51. for(size_t c = 0;c<4;c++)
  52. {
  53. IT(t,c) = IV(T(t,c));
  54. }
  55. }
  56. const auto & extract_rows = [](
  57. const PlainObjectBase<DerivedT> & T,
  58. const MatrixX4S & IT,
  59. const VectorXb & I,
  60. MatrixX4I & TI,
  61. MatrixX4S & ITI,
  62. VectorXI & JI)
  63. {
  64. const Index num_I = std::count(I.data(),I.data()+I.size(),true);
  65. TI.resize(num_I,4);
  66. ITI.resize(num_I,4);
  67. JI.resize(num_I,1);
  68. {
  69. size_t k = 0;
  70. for(size_t t = 0;t<(size_t)T.rows();t++)
  71. {
  72. if(I(t))
  73. {
  74. TI.row(k) = T.row(t);
  75. ITI.row(k) = IT.row(t);
  76. JI(k) = t;
  77. k++;
  78. }
  79. }
  80. assert(k == num_I);
  81. }
  82. };
  83. VectorXb I13 = (IT.array()<0).rowwise().count()==1;
  84. VectorXb I31 = (IT.array()>0).rowwise().count()==1;
  85. VectorXb I22 = (IT.array()<0).rowwise().count()==2;
  86. MatrixX4I T13,T31,T22;
  87. MatrixX4S IT13,IT31,IT22;
  88. VectorXI J13,J31,J22;
  89. extract_rows(T,IT,I13,T13,IT13,J13);
  90. extract_rows(T,IT,I31,T31,IT31,J31);
  91. extract_rows(T,IT,I22,T22,IT22,J22);
  92. const auto & apply_sort = [] (
  93. const MatrixX4I & T,
  94. const MatrixX4I & sJ,
  95. MatrixX4I & sT)
  96. {
  97. sT.resize(T.rows(),4);
  98. for(size_t t = 0;t<(size_t)T.rows();t++)
  99. {
  100. for(size_t c = 0;c<4;c++)
  101. {
  102. sT(t,c) = T(t,sJ(t,c));
  103. }
  104. }
  105. };
  106. const auto & one_below = [&V,&apply_sort](
  107. const MatrixX4I & T,
  108. const MatrixX4S & IT,
  109. MatrixX3I & G,
  110. SparseMatrix<BCType> & BC)
  111. {
  112. // Number of tets
  113. const size_t m = T.rows();
  114. MatrixX4S sIT;
  115. MatrixX4I sJ;
  116. sort(IT,2,true,sIT,sJ);
  117. MatrixX4I sT;
  118. apply_sort(T,sJ,sT);
  119. MatrixX3S lambda =
  120. sIT.rightCols(3).array() /
  121. (sIT.rightCols(3).colwise()-sIT.col(0)).array();
  122. vector<Triplet<BCType> > IJV;
  123. IJV.reserve(m*3*2);
  124. for(size_t c = 0;c<3;c++)
  125. {
  126. for(size_t t = 0;t<(size_t)m;t++)
  127. {
  128. IJV.push_back(Triplet<BCType>(c*m+t, sT(t,0), lambda(t,c)));
  129. IJV.push_back(Triplet<BCType>(c*m+t,sT(t,c+1),1-lambda(t,c)));
  130. }
  131. }
  132. BC.resize(m*3,V.rows());
  133. BC.reserve(m*3*2);
  134. BC.setFromTriplets(IJV.begin(),IJV.end());
  135. G.resize(m,3);
  136. for(size_t c = 0;c<3;c++)
  137. {
  138. G.col(c).setLinSpaced(m,0+c*m,(m-1)+c*m);
  139. }
  140. };
  141. const auto & two_below = [&V,&apply_sort](
  142. const MatrixX4I & T,
  143. const MatrixX4S & IT,
  144. MatrixX3I & G,
  145. SparseMatrix<BCType> & BC)
  146. {
  147. // Number of tets
  148. const size_t m = T.rows();
  149. MatrixX4S sIT;
  150. MatrixX4I sJ;
  151. sort(IT,2,true,sIT,sJ);
  152. MatrixX4I sT;
  153. apply_sort(T,sJ,sT);
  154. MatrixX2S lambda =
  155. sIT.rightCols(2).array() /
  156. (sIT.rightCols(2).colwise()-sIT.col(0)).array();
  157. MatrixX2S gamma =
  158. sIT.rightCols(2).array() /
  159. (sIT.rightCols(2).colwise()-sIT.col(1)).array();
  160. vector<Triplet<BCType> > IJV;
  161. IJV.reserve(m*4*2);
  162. for(size_t c = 0;c<2;c++)
  163. {
  164. for(size_t t = 0;t<(size_t)m;t++)
  165. {
  166. IJV.push_back(Triplet<BCType>(0*2*m+c*m+t, sT(t,0), lambda(t,c)));
  167. IJV.push_back(Triplet<BCType>(0*2*m+c*m+t,sT(t,c+2),1-lambda(t,c)));
  168. IJV.push_back(Triplet<BCType>(1*2*m+c*m+t, sT(t,1), gamma(t,c)));
  169. IJV.push_back(Triplet<BCType>(1*2*m+c*m+t,sT(t,c+2),1- gamma(t,c)));
  170. }
  171. }
  172. BC.resize(m*4,V.rows());
  173. BC.reserve(m*4*2);
  174. BC.setFromTriplets(IJV.begin(),IJV.end());
  175. G.resize(2*m,3);
  176. G.block(0,0,m,1) = VectorXI::LinSpaced(m,0+0*m,(m-1)+0*m);
  177. G.block(0,1,m,1) = VectorXI::LinSpaced(m,0+1*m,(m-1)+1*m);
  178. G.block(0,2,m,1) = VectorXI::LinSpaced(m,0+3*m,(m-1)+3*m);
  179. G.block(m,0,m,1) = VectorXI::LinSpaced(m,0+0*m,(m-1)+0*m);
  180. G.block(m,1,m,1) = VectorXI::LinSpaced(m,0+3*m,(m-1)+3*m);
  181. G.block(m,2,m,1) = VectorXI::LinSpaced(m,0+2*m,(m-1)+2*m);
  182. };
  183. MatrixX3I G13,G31,G22;
  184. SparseMatrix<BCType> BC13,BC31,BC22;
  185. one_below(T13,IT13,G13,BC13);
  186. one_below(T31,-IT31,G31,BC31);
  187. two_below(T22,IT22,G22,BC22);
  188. BC = cat(1,cat(1,BC13,BC31),BC22);
  189. U = BC*V;
  190. G.resize(G13.rows()+G31.rows()+G22.rows(),3);
  191. G<<G13,(G31.array()+BC13.rows()),(G22.array()+BC13.rows()+BC31.rows());
  192. MatrixX3S N;
  193. per_face_normals(U,G,N);
  194. Matrix<Scalar,1,3> planeN(plane(0),plane(1),plane(2));
  195. VectorXb flip = (N.array().rowwise() * planeN.array()).rowwise().sum()<0;
  196. for(size_t g = 0;g<(size_t)G.rows();g++)
  197. {
  198. if(flip(g))
  199. {
  200. G.row(g) = G.row(g).reverse().eval();
  201. }
  202. }
  203. J.resize(G.rows());
  204. J<<J13,J31,J22,J22;
  205. }
  206. #ifdef IGL_STATIC_LIBRARY
  207. // Explicit template specialization
  208. template void igl::slice_tets<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::SparseMatrix<double, 0, int>&);
  209. #endif