triangle_triangle_adjacency.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 Alec Jacobson, Marc Alexa
  4. // Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla Public License
  7. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  8. // obtain one at http://mozilla.org/MPL/2.0/.
  9. #include "triangle_triangle_adjacency.h"
  10. #include "vertex_triangle_adjacency.h"
  11. #include "parallel_for.h"
  12. #include "unique_edge_map.h"
  13. #include <algorithm>
  14. #include <iostream>
  15. // Extract the face adjacencies
  16. template <typename DerivedF, typename TTT_type, typename DerivedTT>
  17. IGL_INLINE void igl::triangle_triangle_adjacency_extractTT(
  18. const Eigen::MatrixBase<DerivedF>& F,
  19. std::vector<std::vector<TTT_type> >& TTT,
  20. Eigen::PlainObjectBase<DerivedTT>& TT)
  21. {
  22. TT.setConstant((int)(F.rows()),F.cols(),-1);
  23. for(int i=1;i<(int)TTT.size();++i)
  24. {
  25. std::vector<int>& r1 = TTT[i-1];
  26. std::vector<int>& r2 = TTT[i];
  27. if ((r1[0] == r2[0]) && (r1[1] == r2[1]))
  28. {
  29. TT(r1[2],r1[3]) = r2[2];
  30. TT(r2[2],r2[3]) = r1[2];
  31. }
  32. }
  33. }
  34. template <typename DerivedF, typename DerivedTT>
  35. IGL_INLINE void igl::triangle_triangle_adjacency(
  36. const Eigen::MatrixBase<DerivedF>& F,
  37. Eigen::PlainObjectBase<DerivedTT>& TT)
  38. {
  39. const int n = F.maxCoeff()+1;
  40. typedef Eigen::Matrix<typename DerivedTT::Scalar,Eigen::Dynamic,1> VectorXI;
  41. VectorXI VF,NI;
  42. vertex_triangle_adjacency(F,n,VF,NI);
  43. TT = DerivedTT::Constant(F.rows(),3,-1);
  44. // Loop over faces
  45. igl::parallel_for(F.rows(),[&](int f)
  46. {
  47. // Loop over corners
  48. for (int k = 0; k < 3; k++)
  49. {
  50. int vi = F(f,k), vin = F(f,(k+1)%3);
  51. // Loop over face neighbors incident on this corner
  52. for (int j = NI[vi]; j < NI[vi+1]; j++)
  53. {
  54. int fn = VF[j];
  55. // Not this face
  56. if (fn != f)
  57. {
  58. // Face neighbor also has [vi,vin] edge
  59. if (F(fn,0) == vin || F(fn,1) == vin || F(fn,2) == vin)
  60. {
  61. TT(f,k) = fn;
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. });
  68. }
  69. template <typename DerivedF, typename TTT_type>
  70. IGL_INLINE void igl::triangle_triangle_adjacency_preprocess(
  71. const Eigen::MatrixBase<DerivedF>& F,
  72. std::vector<std::vector<TTT_type> >& TTT)
  73. {
  74. for(int f=0;f<F.rows();++f)
  75. for (int i=0;i<F.cols();++i)
  76. {
  77. // v1 v2 f ei
  78. int v1 = F(f,i);
  79. int v2 = F(f,(i+1)%F.cols());
  80. if (v1 > v2) std::swap(v1,v2);
  81. std::vector<int> r(4);
  82. r[0] = v1; r[1] = v2;
  83. r[2] = f; r[3] = i;
  84. TTT.push_back(r);
  85. }
  86. std::sort(TTT.begin(),TTT.end());
  87. }
  88. // Extract the face adjacencies indices (needed for fast traversal)
  89. template <typename DerivedF, typename TTT_type, typename DerivedTTi>
  90. IGL_INLINE void igl::triangle_triangle_adjacency_extractTTi(
  91. const Eigen::MatrixBase<DerivedF>& F,
  92. std::vector<std::vector<TTT_type> >& TTT,
  93. Eigen::PlainObjectBase<DerivedTTi>& TTi)
  94. {
  95. TTi.setConstant((int)(F.rows()),F.cols(),-1);
  96. for(int i=1;i<(int)TTT.size();++i)
  97. {
  98. std::vector<int>& r1 = TTT[i-1];
  99. std::vector<int>& r2 = TTT[i];
  100. if ((r1[0] == r2[0]) && (r1[1] == r2[1]))
  101. {
  102. TTi(r1[2],r1[3]) = r2[3];
  103. TTi(r2[2],r2[3]) = r1[3];
  104. }
  105. }
  106. }
  107. // Compute triangle-triangle adjacency with indices
  108. template <typename DerivedF, typename DerivedTT, typename DerivedTTi>
  109. IGL_INLINE void igl::triangle_triangle_adjacency(
  110. const Eigen::MatrixBase<DerivedF>& F,
  111. Eigen::PlainObjectBase<DerivedTT>& TT,
  112. Eigen::PlainObjectBase<DerivedTTi>& TTi)
  113. {
  114. triangle_triangle_adjacency(F,TT);
  115. TTi = DerivedTTi::Constant(TT.rows(),TT.cols(),-1);
  116. //for(int f = 0; f<F.rows(); f++)
  117. igl::parallel_for(F.rows(),[&](int f)
  118. {
  119. for(int k = 0;k<3;k++)
  120. {
  121. int vi = F(f,k), vj = F(f,(k+1)%3);
  122. int fn = TT(f,k);
  123. if(fn >= 0)
  124. {
  125. for(int kn = 0;kn<3;kn++)
  126. {
  127. int vin = F(fn,kn), vjn = F(fn,(kn+1)%3);
  128. if(vi == vjn && vin == vj)
  129. {
  130. TTi(f,k) = kn;
  131. break;
  132. }
  133. }
  134. }
  135. }
  136. });
  137. }
  138. template <
  139. typename DerivedF,
  140. typename TTIndex,
  141. typename TTiIndex>
  142. IGL_INLINE void igl::triangle_triangle_adjacency(
  143. const Eigen::MatrixBase<DerivedF> & F,
  144. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  145. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  146. {
  147. return triangle_triangle_adjacency(F,true,TT,TTi);
  148. }
  149. template <
  150. typename DerivedF,
  151. typename TTIndex>
  152. IGL_INLINE void igl::triangle_triangle_adjacency(
  153. const Eigen::MatrixBase<DerivedF> & F,
  154. std::vector<std::vector<std::vector<TTIndex> > > & TT)
  155. {
  156. std::vector<std::vector<std::vector<TTIndex> > > not_used;
  157. return triangle_triangle_adjacency(F,false,TT,not_used);
  158. }
  159. template <
  160. typename DerivedF,
  161. typename TTIndex,
  162. typename TTiIndex>
  163. IGL_INLINE void igl::triangle_triangle_adjacency(
  164. const Eigen::MatrixBase<DerivedF> & F,
  165. const bool construct_TTi,
  166. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  167. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  168. {
  169. using namespace Eigen;
  170. using namespace std;
  171. assert(F.cols() == 3 && "Faces must be triangles");
  172. // number of faces
  173. typedef typename DerivedF::Index Index;
  174. typedef Matrix<typename DerivedF::Scalar,Dynamic,2> MatrixX2I;
  175. typedef Matrix<typename DerivedF::Index,Dynamic,1> VectorXI;
  176. MatrixX2I E,uE;
  177. VectorXI EMAP;
  178. vector<vector<Index> > uE2E;
  179. unique_edge_map(F,E,uE,EMAP,uE2E);
  180. return triangle_triangle_adjacency(E,EMAP,uE2E,construct_TTi,TT,TTi);
  181. }
  182. template <
  183. typename DerivedE,
  184. typename DerivedEMAP,
  185. typename uE2EType,
  186. typename TTIndex,
  187. typename TTiIndex>
  188. IGL_INLINE void igl::triangle_triangle_adjacency(
  189. const Eigen::MatrixBase<DerivedE> & E,
  190. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  191. const std::vector<std::vector<uE2EType> > & uE2E,
  192. const bool construct_TTi,
  193. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  194. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  195. {
  196. using namespace std;
  197. using namespace Eigen;
  198. typedef typename DerivedE::Index Index;
  199. const size_t m = E.rows()/3;
  200. assert((size_t)E.rows() == m*3 && "E should come from list of triangles.");
  201. // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
  202. // and k
  203. TT.resize (m,vector<vector<TTIndex> >(3));
  204. if(construct_TTi)
  205. {
  206. TTi.resize(m,vector<vector<TTiIndex> >(3));
  207. }
  208. // No race conditions because TT*[f][c]'s are in bijection with e's
  209. // Minimum number of items per thread
  210. //const size_t num_e = E.rows();
  211. // Slightly better memory access than loop over E
  212. igl::parallel_for(
  213. m,
  214. [&](const Index & f)
  215. {
  216. for(Index c = 0;c<3;c++)
  217. {
  218. const Index e = f + m*c;
  219. //const Index c = e/m;
  220. const vector<uE2EType> & N = uE2E[EMAP(e)];
  221. for(const auto & ne : N)
  222. {
  223. const Index nf = ne%m;
  224. // don't add self
  225. if(nf != f)
  226. {
  227. TT[f][c].push_back(nf);
  228. if(construct_TTi)
  229. {
  230. const Index nc = ne/m;
  231. TTi[f][c].push_back(nc);
  232. }
  233. }
  234. }
  235. }
  236. },
  237. 1000ul);
  238. }
  239. #ifdef IGL_STATIC_LIBRARY
  240. // Explicit template instantiation
  241. // generated by autoexplicit.sh
  242. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  243. // generated by autoexplicit.sh
  244. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&);
  245. // generated by autoexplicit.sh
  246. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  247. // generated by autoexplicit.sh
  248. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  249. template void igl::triangle_triangle_adjacency<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::MatrixBase<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> >&);
  250. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  251. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, long, long>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&);
  252. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&);
  253. #ifdef WIN32
  254. template void igl::triangle_triangle_adjacency<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, __int64, __int64>(class Eigen::MatrixBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class std::vector<class std::vector<class std::vector<__int64, class std::allocator<__int64>>, class std::allocator<class std::vector<__int64, class std::allocator<__int64>>>>, class std::allocator<class std::vector<class std::vector<__int64, class std::allocator<__int64>>, class std::allocator<class std::vector<__int64, class std::allocator<__int64>>>>>> &, class std::vector<class std::vector<class std::vector<__int64, class std::allocator<__int64>>, class std::allocator<class std::vector<__int64, class std::allocator<__int64>>>>, class std::allocator<class std::vector<class std::vector<__int64, class std::allocator<__int64>>, class std::allocator<class std::vector<__int64, class std::allocator<__int64>>>>>> &);
  255. template void igl::triangle_triangle_adjacency<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned __int64, int, int>(class Eigen::MatrixBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::MatrixBase<class Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, class std::vector<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>, class std::allocator<class std::vector<unsigned __int64, class std::allocator<unsigned __int64>>>> const &, bool, class std::vector<class std::vector<class std::vector<int, class std::allocator<int>>, class std::allocator<class std::vector<int, class std::allocator<int>>>>, class std::allocator<class std::vector<class std::vector<int, class std::allocator<int>>, class std::allocator<class std::vector<int, class std::allocator<int>>>>>> &, class std::vector<class std::vector<class std::vector<int, class std::allocator<int>>, class std::allocator<class std::vector<int, class std::allocator<int>>>>, class std::allocator<class std::vector<class std::vector<int, class std::allocator<int>>, class std::allocator<class std::vector<int, class std::allocator<int>>>>>> &);
  256. #endif
  257. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long, long, long>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, bool, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&);
  258. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long, int, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, bool, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&);
  259. #endif