slice_tets.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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 "LinSpaced.h"
  10. #include "sort.h"
  11. #include "edges.h"
  12. #include "slice.h"
  13. #include "cat.h"
  14. #include "ismember.h"
  15. #include "unique_rows.h"
  16. #include <cassert>
  17. #include <algorithm>
  18. #include <vector>
  19. template <
  20. typename DerivedV,
  21. typename DerivedT,
  22. typename DerivedS,
  23. typename DerivedSV,
  24. typename DerivedSF,
  25. typename DerivedJ,
  26. typename BCType>
  27. IGL_INLINE void igl::slice_tets(
  28. const Eigen::MatrixBase<DerivedV>& V,
  29. const Eigen::MatrixBase<DerivedT>& T,
  30. const Eigen::MatrixBase<DerivedS> & S,
  31. Eigen::PlainObjectBase<DerivedSV>& SV,
  32. Eigen::PlainObjectBase<DerivedSF>& SF,
  33. Eigen::PlainObjectBase<DerivedJ>& J,
  34. Eigen::SparseMatrix<BCType> & BC)
  35. {
  36. Eigen::MatrixXi sE;
  37. Eigen::Matrix<typename DerivedSV::Scalar,Eigen::Dynamic,1> lambda;
  38. igl::slice_tets(V,T,S,SV,SF,J,sE,lambda);
  39. const int ns = SV.rows();
  40. std::vector<Eigen::Triplet<BCType> > BCIJV(ns*2);
  41. for(int i = 0;i<ns;i++)
  42. {
  43. BCIJV[2*i+0] = Eigen::Triplet<BCType>(i,sE(i,0), lambda(i));
  44. BCIJV[2*i+1] = Eigen::Triplet<BCType>(i,sE(i,1),1.0-lambda(i));
  45. }
  46. BC.resize(SV.rows(),V.rows());
  47. BC.setFromTriplets(BCIJV.begin(),BCIJV.end());
  48. }
  49. template <
  50. typename DerivedV,
  51. typename DerivedT,
  52. typename DerivedS,
  53. typename DerivedSV,
  54. typename DerivedSF,
  55. typename DerivedJ>
  56. IGL_INLINE void igl::slice_tets(
  57. const Eigen::MatrixBase<DerivedV>& V,
  58. const Eigen::MatrixBase<DerivedT>& T,
  59. const Eigen::MatrixBase<DerivedS> & S,
  60. Eigen::PlainObjectBase<DerivedSV>& SV,
  61. Eigen::PlainObjectBase<DerivedSF>& SF,
  62. Eigen::PlainObjectBase<DerivedJ>& J)
  63. {
  64. Eigen::MatrixXi sE;
  65. Eigen::Matrix<typename DerivedSV::Scalar,Eigen::Dynamic,1> lambda;
  66. igl::slice_tets(V,T,S,SV,SF,J,sE,lambda);
  67. }
  68. template <
  69. typename DerivedV,
  70. typename DerivedT,
  71. typename DerivedS,
  72. typename DerivedSV,
  73. typename DerivedSF,
  74. typename DerivedJ,
  75. typename DerivedsE,
  76. typename Derivedlambda>
  77. IGL_INLINE void igl::slice_tets(
  78. const Eigen::MatrixBase<DerivedV>& V,
  79. const Eigen::MatrixBase<DerivedT>& T,
  80. const Eigen::MatrixBase<DerivedS> & S,
  81. Eigen::PlainObjectBase<DerivedSV>& SV,
  82. Eigen::PlainObjectBase<DerivedSF>& SF,
  83. Eigen::PlainObjectBase<DerivedJ>& J,
  84. Eigen::PlainObjectBase<DerivedsE>& sE,
  85. Eigen::PlainObjectBase<Derivedlambda>& lambda)
  86. {
  87. using namespace Eigen;
  88. using namespace std;
  89. assert(V.cols() == 3 && "V should be #V by 3");
  90. assert(T.cols() == 4 && "T should be #T by 4");
  91. static const Eigen::Matrix<int,12,4> flipped_order =
  92. (Eigen::Matrix<int,12,4>(12,4)<<
  93. 3,2,0,1,
  94. 3,1,2,0,
  95. 3,0,1,2,
  96. 2,3,1,0,
  97. 2,1,0,3,
  98. 2,0,3,1,
  99. 1,3,0,2,
  100. 1,2,3,0,
  101. 1,0,2,3,
  102. 0,3,2,1,
  103. 0,2,1,3,
  104. 0,1,3,2
  105. ).finished();
  106. // number of tets
  107. const size_t m = T.rows();
  108. typedef typename DerivedS::Scalar Scalar;
  109. typedef typename DerivedT::Scalar Index;
  110. typedef Matrix<Scalar,Dynamic,1> VectorXS;
  111. typedef Matrix<Scalar,Dynamic,4> MatrixX4S;
  112. typedef Matrix<Scalar,Dynamic,3> MatrixX3S;
  113. typedef Matrix<Scalar,Dynamic,2> MatrixX2S;
  114. typedef Matrix<Index,Dynamic,4> MatrixX4I;
  115. typedef Matrix<Index,Dynamic,3> MatrixX3I;
  116. typedef Matrix<Index,Dynamic,2> MatrixX2I;
  117. typedef Matrix<Index,Dynamic,1> VectorXI;
  118. typedef Array<bool,Dynamic,1> ArrayXb;
  119. MatrixX4S IT(m,4);
  120. for(size_t t = 0;t<m;t++)
  121. {
  122. for(size_t c = 0;c<4;c++)
  123. {
  124. IT(t,c) = S(T(t,c));
  125. }
  126. }
  127. // Essentially, just a glorified slice(X,1)
  128. //
  129. // Inputs:
  130. // T #T by 4 list of tet indices into V
  131. // IT #IT by 4 list of isosurface values at each tet
  132. // I #I list of bools whether to grab data corresponding to each tet
  133. const auto & extract_rows = [](
  134. const MatrixBase<DerivedT> & T,
  135. const MatrixX4S & IT,
  136. const ArrayXb & I,
  137. MatrixX4I & TI,
  138. MatrixX4S & ITI,
  139. VectorXI & JI)
  140. {
  141. const Index num_I = std::count(I.data(),I.data()+I.size(),true);
  142. TI.resize(num_I,4);
  143. ITI.resize(num_I,4);
  144. JI.resize(num_I,1);
  145. {
  146. size_t k = 0;
  147. for(size_t t = 0;t<(size_t)T.rows();t++)
  148. {
  149. if(I(t))
  150. {
  151. TI.row(k) = T.row(t);
  152. ITI.row(k) = IT.row(t);
  153. JI(k) = t;
  154. k++;
  155. }
  156. }
  157. assert(k == num_I);
  158. }
  159. };
  160. ArrayXb I13 = (IT.array()<0).rowwise().count()==1;
  161. ArrayXb I31 = (IT.array()>0).rowwise().count()==1;
  162. ArrayXb I22 = (IT.array()<0).rowwise().count()==2;
  163. MatrixX4I T13,T31,T22;
  164. MatrixX4S IT13,IT31,IT22;
  165. VectorXI J13,J31,J22;
  166. extract_rows(T,IT,I13,T13,IT13,J13);
  167. extract_rows(T,IT,I31,T31,IT31,J31);
  168. extract_rows(T,IT,I22,T22,IT22,J22);
  169. const auto & apply_sort4 = [] (
  170. const MatrixX4I & T,
  171. const MatrixX4I & sJ,
  172. MatrixX4I & sT)
  173. {
  174. sT.resize(T.rows(),4);
  175. for(size_t t = 0;t<(size_t)T.rows();t++)
  176. {
  177. for(size_t c = 0;c<4;c++)
  178. {
  179. sT(t,c) = T(t,sJ(t,c));
  180. }
  181. }
  182. };
  183. const auto & apply_sort2 = [] (
  184. const MatrixX2I & E,
  185. const MatrixX2I & sJ,
  186. Eigen::PlainObjectBase<DerivedsE>& sE)
  187. {
  188. sE.resize(E.rows(),2);
  189. for(size_t t = 0;t<(size_t)E.rows();t++)
  190. {
  191. for(size_t c = 0;c<2;c++)
  192. {
  193. sE(t,c) = E(t,sJ(t,c));
  194. }
  195. }
  196. };
  197. const auto & one_below = [&apply_sort4](
  198. const MatrixX4I & T,
  199. const MatrixX4S & IT,
  200. MatrixX2I & U,
  201. MatrixX3I & SF)
  202. {
  203. // Number of tets
  204. const size_t m = T.rows();
  205. if(m == 0)
  206. {
  207. U.resize(0,2);
  208. SF.resize(0,3);
  209. return;
  210. }
  211. MatrixX4S sIT;
  212. MatrixX4I sJ;
  213. sort(IT,2,true,sIT,sJ);
  214. MatrixX4I sT;
  215. apply_sort4(T,sJ,sT);
  216. U.resize(3*m,2);
  217. U<<
  218. sT.col(0),sT.col(1),
  219. sT.col(0),sT.col(2),
  220. sT.col(0),sT.col(3);
  221. SF.resize(m,3);
  222. for(size_t c = 0;c<3;c++)
  223. {
  224. SF.col(c) =
  225. igl::LinSpaced<
  226. Eigen::Matrix<typename DerivedSF::Scalar,Eigen::Dynamic,1> >
  227. (m,0+c*m,(m-1)+c*m);
  228. }
  229. ArrayXb flip;
  230. {
  231. VectorXi _;
  232. ismember_rows(sJ,flipped_order,flip,_);
  233. }
  234. for(int i = 0;i<m;i++)
  235. {
  236. if(flip(i))
  237. {
  238. SF.row(i) = SF.row(i).reverse().eval();
  239. }
  240. }
  241. };
  242. const auto & two_below = [&apply_sort4](
  243. const MatrixX4I & T,
  244. const MatrixX4S & IT,
  245. MatrixX2I & U,
  246. MatrixX3I & SF)
  247. {
  248. // Number of tets
  249. const size_t m = T.rows();
  250. if(m == 0)
  251. {
  252. U.resize(0,2);
  253. SF.resize(0,3);
  254. return;
  255. }
  256. MatrixX4S sIT;
  257. MatrixX4I sJ;
  258. sort(IT,2,true,sIT,sJ);
  259. MatrixX4I sT;
  260. apply_sort4(T,sJ,sT);
  261. U.resize(4*m,2);
  262. U<<
  263. sT.col(0),sT.col(2),
  264. sT.col(0),sT.col(3),
  265. sT.col(1),sT.col(2),
  266. sT.col(1),sT.col(3);
  267. SF.resize(2*m,3);
  268. SF.block(0,0,m,1) = igl::LinSpaced<VectorXI >(m,0+0*m,(m-1)+0*m);
  269. SF.block(0,1,m,1) = igl::LinSpaced<VectorXI >(m,0+1*m,(m-1)+1*m);
  270. SF.block(0,2,m,1) = igl::LinSpaced<VectorXI >(m,0+3*m,(m-1)+3*m);
  271. SF.block(m,0,m,1) = igl::LinSpaced<VectorXI >(m,0+0*m,(m-1)+0*m);
  272. SF.block(m,1,m,1) = igl::LinSpaced<VectorXI >(m,0+3*m,(m-1)+3*m);
  273. SF.block(m,2,m,1) = igl::LinSpaced<VectorXI >(m,0+2*m,(m-1)+2*m);
  274. ArrayXb flip;
  275. {
  276. VectorXi _;
  277. ismember_rows(sJ,flipped_order,flip,_);
  278. }
  279. for(int i = 0;i<m;i++)
  280. {
  281. if(flip(i))
  282. {
  283. SF.row(i ) = SF.row(i ).reverse().eval();
  284. SF.row(i+m) = SF.row(i+m).reverse().eval();
  285. }
  286. }
  287. };
  288. MatrixX3I SF13,SF31,SF22;
  289. MatrixX2I U13,U31,U22;
  290. one_below(T13, IT13,U13,SF13);
  291. one_below(T31,-IT31,U31,SF31);
  292. two_below(T22, IT22,U22,SF22);
  293. // https://forum.kde.org/viewtopic.php?f=74&t=107974
  294. const MatrixX2I U =
  295. (MatrixX2I(U13.rows()+ U31.rows()+ U22.rows(),2)<<U13,U31,U22).finished();
  296. MatrixX2I sU;
  297. {
  298. MatrixX2I _;
  299. sort(U,2,true,sU,_);
  300. }
  301. MatrixX2I E;
  302. VectorXI uI,uJ;
  303. unique_rows(sU,E,uI,uJ);
  304. MatrixX2S IE(E.rows(),2);
  305. for(size_t t = 0;t<E.rows();t++)
  306. {
  307. for(size_t c = 0;c<2;c++)
  308. {
  309. IE(t,c) = S(E(t,c));
  310. }
  311. }
  312. MatrixX2S sIE;
  313. MatrixX2I sJ;
  314. sort(IE,2,true,sIE,sJ);
  315. apply_sort2(E,sJ,sE);
  316. lambda = sIE.col(1).array() / (sIE.col(1)-sIE.col(0)).array();
  317. SV.resize(sE.rows(),V.cols());
  318. for(int e = 0;e<sE.rows();e++)
  319. {
  320. SV.row(e) = V.row(sE(e,0)).template cast<Scalar>()*lambda(e) +
  321. V.row(sE(e,1)).template cast<Scalar>()*(1.0-lambda(e));
  322. }
  323. SF.resize( SF13.rows()+SF31.rows()+SF22.rows(),3);
  324. SF<<
  325. SF13,
  326. U13.rows()+ SF31.rowwise().reverse().array(),
  327. U13.rows()+U31.rows()+SF22.array();
  328. std::for_each(
  329. SF.data(),
  330. SF.data()+SF.size(),
  331. [&uJ](typename DerivedSF::Scalar & i){i=uJ(i);});
  332. J.resize(SF.rows());
  333. J<<J13,J31,J22,J22;
  334. }
  335. #ifdef IGL_STATIC_LIBRARY
  336. // Explicit template instantiation
  337. 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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<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>&);
  338. #endif