slice_tets.cpp 7.7 KB

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