unique.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 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 "unique.h"
  9. #include "sort.h"
  10. #include "IndexComparison.h"
  11. #include "SortableRow.h"
  12. #include "sortrows.h"
  13. #include "list_to_matrix.h"
  14. #include "matrix_to_list.h"
  15. #include "get_seconds.h"
  16. #include <algorithm>
  17. #include <iostream>
  18. #include <map>
  19. template <typename T>
  20. IGL_INLINE void igl::unique(
  21. const std::vector<T> & A,
  22. std::vector<T> & C,
  23. std::vector<size_t> & IA,
  24. std::vector<size_t> & IC)
  25. {
  26. using namespace std;
  27. std::vector<size_t> IM;
  28. std::vector<T> sortA;
  29. igl::sort(A,true,sortA,IM);
  30. // Original unsorted index map
  31. IA.resize(sortA.size());
  32. for(int i=0;i<(int)sortA.size();i++)
  33. {
  34. IA[i] = i;
  35. }
  36. IA.erase(
  37. std::unique(
  38. IA.begin(),
  39. IA.end(),
  40. igl::IndexEquals<const std::vector<T>& >(sortA)),IA.end());
  41. IC.resize(A.size());
  42. {
  43. int j = 0;
  44. for(int i = 0;i<(int)sortA.size();i++)
  45. {
  46. if(sortA[IA[j]] != sortA[i])
  47. {
  48. j++;
  49. }
  50. IC[IM[i]] = j;
  51. }
  52. }
  53. C.resize(IA.size());
  54. // Reindex IA according to IM
  55. for(int i = 0;i<(int)IA.size();i++)
  56. {
  57. IA[i] = IM[IA[i]];
  58. C[i] = A[IA[i]];
  59. }
  60. }
  61. template <typename T>
  62. IGL_INLINE void igl::unique(
  63. const std::vector<T> & A,
  64. std::vector<T> & C)
  65. {
  66. std::vector<size_t> IA,IC;
  67. return igl::unique(A,C,IA,IC);
  68. }
  69. template <
  70. typename DerivedA,
  71. typename DerivedC,
  72. typename DerivedIA,
  73. typename DerivedIC>
  74. IGL_INLINE void igl::unique(
  75. const Eigen::PlainObjectBase<DerivedA> & A,
  76. Eigen::PlainObjectBase<DerivedC> & C,
  77. Eigen::PlainObjectBase<DerivedIA> & IA,
  78. Eigen::PlainObjectBase<DerivedIC> & IC)
  79. {
  80. using namespace std;
  81. using namespace Eigen;
  82. vector<typename DerivedA::Scalar > vA;
  83. vector<typename DerivedC::Scalar > vC;
  84. vector<size_t> vIA,vIC;
  85. matrix_to_list(A,vA);
  86. unique(vA,vC,vIA,vIC);
  87. list_to_matrix(vC,C);
  88. list_to_matrix(vIA,IA);
  89. list_to_matrix(vIC,IC);
  90. }
  91. template <
  92. typename DerivedA,
  93. typename DerivedC,
  94. typename DerivedIA,
  95. typename DerivedIC>
  96. IGL_INLINE void igl::unique(
  97. const Eigen::PlainObjectBase<DerivedA> & A,
  98. Eigen::PlainObjectBase<DerivedC> & C)
  99. {
  100. using namespace std;
  101. using namespace Eigen;
  102. vector<typename DerivedA::Scalar > vA;
  103. vector<typename DerivedC::Scalar > vC;
  104. vector<size_t> vIA,vIC;
  105. matrix_to_list(A,vA);
  106. unique(vA,vC,vIA,vIC);
  107. list_to_matrix(vC,C);
  108. }
  109. // Obsolete slow version converting to vectors
  110. // template <typename DerivedA, typename DerivedIA, typename DerivedIC>
  111. // IGL_INLINE void igl::unique_rows(
  112. // const Eigen::PlainObjectBase<DerivedA>& A,
  113. // Eigen::PlainObjectBase<DerivedA>& C,
  114. // Eigen::PlainObjectBase<DerivedIA>& IA,
  115. // Eigen::PlainObjectBase<DerivedIC>& IC)
  116. // {
  117. // using namespace std;
  118. //
  119. // typedef Eigen::Matrix<typename DerivedA::Scalar, Eigen::Dynamic, 1> RowVector;
  120. // vector<SortableRow<RowVector> > rows;
  121. // rows.resize(A.rows());
  122. // // Loop over rows
  123. // for(int i = 0;i<A.rows();i++)
  124. // {
  125. // RowVector ri = A.row(i);
  126. // rows[i] = SortableRow<RowVector>(ri);
  127. // }
  128. // vector<SortableRow<RowVector> > vC;
  129. //
  130. // // unique on rows
  131. // vector<size_t> vIA;
  132. // vector<size_t> vIC;
  133. // unique(rows,vC,vIA,vIC);
  134. //
  135. // // Convert to eigen
  136. // C.resize(vC.size(),A.cols());
  137. // IA.resize(vIA.size(),1);
  138. // IC.resize(vIC.size(),1);
  139. // for(int i = 0;i<C.rows();i++)
  140. // {
  141. // C.row(i) = vC[i].data;
  142. // IA(i) = vIA[i];
  143. // }
  144. // for(int i = 0;i<A.rows();i++)
  145. // {
  146. // IC(i) = vIC[i];
  147. // }
  148. // }
  149. // Obsolete
  150. // template <typename DerivedA, typename DerivedIA, typename DerivedIC>
  151. // IGL_INLINE void igl::unique_rows_many(
  152. // const Eigen::PlainObjectBase<DerivedA>& A,
  153. // Eigen::PlainObjectBase<DerivedA>& C,
  154. // Eigen::PlainObjectBase<DerivedIA>& IA,
  155. // Eigen::PlainObjectBase<DerivedIC>& IC)
  156. // {
  157. // using namespace std;
  158. // // frequency map
  159. // typedef Eigen::Matrix<typename DerivedA::Scalar, Eigen::Dynamic, 1> RowVector;
  160. // IC.resize(A.rows(),1);
  161. // map<SortableRow<RowVector>, int> fm;
  162. // const int m = A.rows();
  163. // for(int i = 0;i<m;i++)
  164. // {
  165. // RowVector ri = A.row(i);
  166. // if(fm.count(SortableRow<RowVector>(ri)) == 0)
  167. // {
  168. // fm[SortableRow<RowVector>(ri)] = i;
  169. // }
  170. // IC(i) = fm[SortableRow<RowVector>(ri)];
  171. // }
  172. // IA.resize(fm.size(),1);
  173. // Eigen::VectorXi RIA(m);
  174. // C.resize(fm.size(),A.cols());
  175. // {
  176. // int i = 0;
  177. // for(typename map<SortableRow<RowVector > , int >::const_iterator fit = fm.begin();
  178. // fit != fm.end();
  179. // fit++)
  180. // {
  181. // IA(i) = fit->second;
  182. // RIA(fit->second) = i;
  183. // C.row(i) = fit->first.data;
  184. // i++;
  185. // }
  186. // }
  187. // // IC should index C
  188. // for(int i = 0;i<m;i++)
  189. // {
  190. // IC(i) = RIA(IC(i));
  191. // }
  192. // }
  193. template <typename DerivedA, typename DerivedIA, typename DerivedIC>
  194. IGL_INLINE void igl::unique_rows(
  195. const Eigen::PlainObjectBase<DerivedA>& A,
  196. Eigen::PlainObjectBase<DerivedA>& C,
  197. Eigen::PlainObjectBase<DerivedIA>& IA,
  198. Eigen::PlainObjectBase<DerivedIC>& IC)
  199. {
  200. using namespace std;
  201. using namespace igl;
  202. using namespace Eigen;
  203. VectorXi IM;
  204. Eigen::PlainObjectBase<DerivedA> sortA;
  205. sortrows(A,true,sortA,IM);
  206. vector<int> vIA(sortA.rows());
  207. for(int i=0;i<(int)sortA.rows();i++)
  208. {
  209. vIA[i] = i;
  210. }
  211. vIA.erase(
  212. std::unique(
  213. vIA.begin(),
  214. vIA.end(),
  215. igl::IndexRowEquals<const Eigen::PlainObjectBase<DerivedA> &>(sortA)),vIA.end());
  216. IC.resize(A.rows(),1);
  217. {
  218. int j = 0;
  219. for(int i = 0;i<(int)sortA.rows();i++)
  220. {
  221. if(sortA.row(vIA[j]) != sortA.row(i))
  222. {
  223. j++;
  224. }
  225. IC(IM(i,0),0) = j;
  226. }
  227. }
  228. C.resize(vIA.size(),A.cols());
  229. IA.resize(vIA.size(),1);
  230. // Reindex IA according to IM
  231. for(int i = 0;i<(int)vIA.size();i++)
  232. {
  233. IA(i,0) = IM(vIA[i],0);
  234. C.row(i) = A.row(IA(i,0));
  235. }
  236. }
  237. #ifdef IGL_STATIC_LIBRARY
  238. // Explicit template specialization
  239. template void igl::unique<int>(std::vector<int, std::allocator<int> > const&, std::vector<int, std::allocator<int> >&, std::vector<size_t, std::allocator<size_t> >&, std::vector<size_t, std::allocator<size_t> >&);
  240. template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
  241. template void igl::unique_rows<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(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> >&);
  242. template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
  243. template void igl::unique_rows<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(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> >&);
  244. template void igl::unique_rows<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  245. template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
  246. template void igl::unique<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
  247. template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
  248. template void igl::unique<int>(std::vector<int, std::allocator<int> > const&, std::vector<int, std::allocator<int> >&);
  249. template void igl::unique<long>(std::vector<long, std::allocator<long> > const&, std::vector<long, std::allocator<long> >&, std::vector<unsigned long, std::allocator<unsigned long> >&, std::vector<unsigned long, std::allocator<unsigned long> >&);
  250. #endif