slice.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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 "slice.h"
  9. #include "colon.h"
  10. #include <cassert>
  11. #include <vector>
  12. template <
  13. typename TX,
  14. typename TY,
  15. typename DerivedR,
  16. typename DerivedC>
  17. IGL_INLINE void igl::slice(
  18. const Eigen::SparseMatrix<TX> &X,
  19. const Eigen::DenseBase<DerivedR> &R,
  20. const Eigen::DenseBase<DerivedC> &C,
  21. Eigen::SparseMatrix<TY> &Y)
  22. {
  23. int xm = X.rows();
  24. int xn = X.cols();
  25. int ym = R.size();
  26. int yn = C.size();
  27. // special case when R or C is empty
  28. if (ym == 0 || yn == 0)
  29. {
  30. Y.resize(ym, yn);
  31. return;
  32. }
  33. assert(R.minCoeff() >= 0);
  34. assert(R.maxCoeff() < xm);
  35. assert(C.minCoeff() >= 0);
  36. assert(C.maxCoeff() < xn);
  37. // Build reindexing maps for columns and rows
  38. std::vector<std::vector<typename DerivedR::Scalar>> RI;
  39. RI.resize(xm);
  40. for (int i = 0; i < ym; i++)
  41. {
  42. RI[R(i)].push_back(i);
  43. }
  44. std::vector<std::vector<typename DerivedC::Scalar>> CI;
  45. CI.resize(xn);
  46. for (int i = 0; i < yn; i++)
  47. {
  48. CI[C(i)].push_back(i);
  49. }
  50. // Take a guess at the number of nonzeros (this assumes uniform distribution
  51. // not banded or heavily diagonal)
  52. std::vector<Eigen::Triplet<TY>> entries;
  53. entries.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn));
  54. // Iterate over outside
  55. for (int k = 0; k < X.outerSize(); ++k)
  56. {
  57. // Iterate over inside
  58. for (typename Eigen::SparseMatrix<TX>::InnerIterator it(X, k); it; ++it)
  59. {
  60. for (auto rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++)
  61. {
  62. for (auto cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++)
  63. {
  64. entries.emplace_back(*rit, *cit, it.value());
  65. }
  66. }
  67. }
  68. }
  69. Y.resize(ym, yn);
  70. Y.setFromTriplets(entries.begin(), entries.end());
  71. }
  72. template <typename MatX, typename DerivedR, typename MatY>
  73. IGL_INLINE void igl::slice(
  74. const MatX &X,
  75. const Eigen::DenseBase<DerivedR> &R,
  76. const int dim,
  77. MatY &Y)
  78. {
  79. Eigen::Matrix<typename DerivedR::Scalar, Eigen::Dynamic, 1> C;
  80. switch (dim)
  81. {
  82. case 1:
  83. // boring base case
  84. if (X.cols() == 0)
  85. {
  86. Y.resize(R.size(), 0);
  87. return;
  88. }
  89. igl::colon(0, X.cols() - 1, C);
  90. return slice(X, R, C, Y);
  91. case 2:
  92. // boring base case
  93. if (X.rows() == 0)
  94. {
  95. Y.resize(0, R.size());
  96. return;
  97. }
  98. igl::colon(0, X.rows() - 1, C);
  99. return slice(X, C, R, Y);
  100. default:
  101. assert(false && "Unsupported dimension");
  102. return;
  103. }
  104. }
  105. template <
  106. typename DerivedX,
  107. typename DerivedR,
  108. typename DerivedC,
  109. typename DerivedY>
  110. IGL_INLINE void igl::slice(
  111. const Eigen::DenseBase<DerivedX> &X,
  112. const Eigen::DenseBase<DerivedR> &R,
  113. const Eigen::DenseBase<DerivedC> &C,
  114. Eigen::PlainObjectBase<DerivedY> &Y)
  115. {
  116. #ifndef NDEBUG
  117. int xm = X.rows();
  118. int xn = X.cols();
  119. #endif
  120. int ym = R.size();
  121. int yn = C.size();
  122. // special case when R or C is empty
  123. if (ym == 0 || yn == 0)
  124. {
  125. Y.resize(ym, yn);
  126. return;
  127. }
  128. assert(R.minCoeff() >= 0);
  129. assert(R.maxCoeff() < xm);
  130. assert(C.minCoeff() >= 0);
  131. assert(C.maxCoeff() < xn);
  132. // Resize output
  133. Y.resize(ym, yn);
  134. // loop over output rows, then columns
  135. for (int i = 0; i < ym; i++)
  136. {
  137. for (int j = 0; j < yn; j++)
  138. {
  139. Y(i, j) = X(R(i), C(j));
  140. }
  141. }
  142. }
  143. template <typename DerivedX, typename DerivedY, typename DerivedR>
  144. IGL_INLINE void igl::slice(
  145. const Eigen::DenseBase<DerivedX> &X,
  146. const Eigen::DenseBase<DerivedR> &R,
  147. Eigen::PlainObjectBase<DerivedY> &Y)
  148. {
  149. // phony column indices
  150. Eigen::Matrix<typename DerivedR::Scalar, Eigen::Dynamic, 1> C;
  151. C.resize(1);
  152. C(0) = 0;
  153. return igl::slice(X, R, C, Y);
  154. }
  155. template <typename DerivedX, typename DerivedR>
  156. IGL_INLINE DerivedX igl::slice(
  157. const Eigen::DenseBase<DerivedX> &X,
  158. const Eigen::DenseBase<DerivedR> &R)
  159. {
  160. // This is not safe. See PlainMatrix
  161. DerivedX Y;
  162. igl::slice(X, R, Y);
  163. return Y;
  164. }
  165. template <typename DerivedX, typename DerivedR>
  166. IGL_INLINE DerivedX igl::slice(
  167. const Eigen::DenseBase<DerivedX> &X,
  168. const Eigen::DenseBase<DerivedR> &R,
  169. const int dim)
  170. {
  171. // This is not safe. See PlainMatrix
  172. DerivedX Y;
  173. igl::slice(X, R, dim, Y);
  174. return Y;
  175. }
  176. template< class T >
  177. IGL_INLINE void igl::slice(
  178. const std::vector<T> & unordered,
  179. std::vector<size_t> const & index_map,
  180. std::vector<T> & ordered)
  181. {
  182. // copy for the slice according to index_map, because unordered may also be
  183. // ordered
  184. std::vector<T> copy = unordered;
  185. ordered.resize(index_map.size());
  186. for(int i = 0; i<(int)index_map.size();i++)
  187. {
  188. ordered[i] = copy[index_map[i]];
  189. }
  190. }
  191. #ifdef IGL_STATIC_LIBRARY
  192. // Explicit template instantiation
  193. template void igl::slice<std::int64_t>(std::vector<std::int64_t, std::allocator<std::int64_t>> const&, std::vector<size_t, std::allocator<size_t>> const&, std::vector<std::int64_t, std::allocator<std::int64_t>>&);
  194. template void igl::slice<Eigen::SparseMatrix<bool, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<bool, 0, int>>(Eigen::SparseMatrix<bool, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<bool, 0, int> &);
  195. template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Array<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Array<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);
  196. template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
  197. template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
  198. template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int>>(Eigen::SparseMatrix<double, 0, int> const &, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, int, Eigen::SparseMatrix<double, 0, int> &);
  199. #ifdef WIN32
  200. template void igl::slice<unsigned int>(class std::vector<unsigned int,class std::allocator<unsigned int> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<unsigned int,class std::allocator<unsigned int> > &);
  201. template void igl::slice<float>(class std::vector<float,class std::allocator<float> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<float,class std::allocator<float> > &);
  202. template void igl::slice<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<__int64,class std::allocator<__int64> > &);
  203. #endif
  204. template void igl::slice<unsigned int>(std::vector<unsigned int, std::allocator<unsigned int> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<unsigned int, std::allocator<unsigned int> >&);
  205. template void igl::slice<float>(std::vector<float, std::allocator<float> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<float, std::allocator<float> >&);
  206. template void igl::slice<double>(std::vector<double, std::allocator<double> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<double, std::allocator<double> >&);
  207. template void igl::slice<int>(std::vector<int, std::allocator<int> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<int, std::allocator<int> >&);
  208. #include "SortableRow.h"
  209. template void igl::slice<igl::SortableRow<Eigen::Matrix<int, -1, 1, 0, -1, 1> > >(std::vector<igl::SortableRow<Eigen::Matrix<int, -1, 1, 0, -1, 1> >, std::allocator<igl::SortableRow<Eigen::Matrix<int, -1, 1, 0, -1, 1> > > > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<igl::SortableRow<Eigen::Matrix<int, -1, 1, 0, -1, 1> >, std::allocator<igl::SortableRow<Eigen::Matrix<int, -1, 1, 0, -1, 1> > > >&);
  210. template void igl::slice<igl::SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> > >(std::vector<igl::SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> >, std::allocator<igl::SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> > > > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<igl::SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> >, std::allocator<igl::SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> > > >&);
  211. #endif