triangle_triangle_adjacency.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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 <[email protected]>
  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. assert(F.cols() == 3 && "Faces must be triangles");
  170. // number of faces
  171. typedef typename DerivedF::Index Index;
  172. typedef Eigen::Matrix<typename DerivedF::Scalar ,Eigen::Dynamic,2> MatrixX2I;
  173. typedef Eigen::Matrix<typename DerivedF::Index ,Eigen::Dynamic,1> VectorXI;
  174. MatrixX2I E,uE;
  175. VectorXI EMAP;
  176. std::vector<std::vector<Index> > uE2E;
  177. unique_edge_map(F,E,uE,EMAP,uE2E);
  178. return triangle_triangle_adjacency(E,EMAP,uE2E,construct_TTi,TT,TTi);
  179. }
  180. template <
  181. typename DerivedE,
  182. typename DerivedEMAP,
  183. typename uE2EType,
  184. typename TTIndex,
  185. typename TTiIndex>
  186. IGL_INLINE void igl::triangle_triangle_adjacency(
  187. const Eigen::MatrixBase<DerivedE> & E,
  188. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  189. const std::vector<std::vector<uE2EType> > & uE2E,
  190. const bool construct_TTi,
  191. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  192. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  193. {
  194. typedef typename DerivedE::Index Index;
  195. const size_t m = E.rows()/3;
  196. assert((size_t)E.rows() == m*3 && "E should come from list of triangles.");
  197. // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
  198. // and k
  199. TT.resize (m,std::vector<std::vector<TTIndex> >(3));
  200. if(construct_TTi)
  201. {
  202. TTi.resize(m,std::vector<std::vector<TTiIndex> >(3));
  203. }
  204. // No race conditions because TT*[f][c]'s are in bijection with e's
  205. // Minimum number of items per thread
  206. //const size_t num_e = E.rows();
  207. // Slightly better memory access than loop over E
  208. igl::parallel_for(
  209. m,
  210. [&](const Index & f)
  211. {
  212. for(Index c = 0;c<3;c++)
  213. {
  214. const Index e = f + m*c;
  215. //const Index c = e/m;
  216. const std::vector<uE2EType> & N = uE2E[EMAP(e)];
  217. for(const auto & ne : N)
  218. {
  219. const Index nf = ne%m;
  220. // don't add self
  221. if(nf != f)
  222. {
  223. TT[f][c].push_back(nf);
  224. if(construct_TTi)
  225. {
  226. const Index nc = ne/m;
  227. TTi[f][c].push_back(nc);
  228. }
  229. }
  230. }
  231. }
  232. },
  233. 1000ul);
  234. }
  235. template <
  236. typename DerivedEMAP,
  237. typename DeriveduEC,
  238. typename DeriveduEE,
  239. typename TTIndex,
  240. typename TTiIndex>
  241. IGL_INLINE void igl::triangle_triangle_adjacency(
  242. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  243. const Eigen::MatrixBase<DeriveduEC> & uEC,
  244. const Eigen::MatrixBase<DeriveduEE> & uEE,
  245. const bool construct_TTi,
  246. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  247. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  248. {
  249. typedef Eigen::Index Index;
  250. const size_t m = EMAP.rows()/3;
  251. assert((size_t)EMAP.rows() == m*3 && "EMAP should come from list of triangles.");
  252. // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
  253. // and k
  254. TT.resize (m,std::vector<std::vector<TTIndex> >(3));
  255. if(construct_TTi)
  256. {
  257. TTi.resize(m,std::vector<std::vector<TTiIndex> >(3));
  258. }
  259. // No race conditions because TT*[f][c]'s are in bijection with e's
  260. // Minimum number of items per thread
  261. //const size_t num_e = E.rows();
  262. // Slightly better memory access than loop over E
  263. igl::parallel_for(
  264. m,
  265. [&](const Index & f)
  266. {
  267. for(Index c = 0;c<3;c++)
  268. {
  269. const Index e = f + m*c;
  270. //const Index c = e/m;
  271. //const vector<uE2EType> & N = uE2E[EMAP(e)];
  272. //for(const auto & ne : N)
  273. for(Index j = uEC(EMAP(e));j<uEC(EMAP(e)+1);j++)
  274. {
  275. const auto ne = uEE(j);
  276. const Index nf = ne%m;
  277. // don't add self
  278. if(nf != f)
  279. {
  280. TT[f][c].push_back(nf);
  281. if(construct_TTi)
  282. {
  283. const Index nc = ne/m;
  284. TTi[f][c].push_back(nc);
  285. }
  286. }
  287. }
  288. }
  289. },
  290. 1000ul);
  291. }
  292. #ifdef IGL_STATIC_LIBRARY
  293. // Explicit template instantiation
  294. // generated by autoexplicit.sh
  295. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, 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>>>>>>&, 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>>>>>>&);
  296. // generated by autoexplicit.sh
  297. 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>, int, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > 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> > > > > >&);
  298. // generated by autoexplicit.sh
  299. 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> >&);
  300. // generated by autoexplicit.sh
  301. 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> > > > > >&);
  302. // generated by autoexplicit.sh
  303. 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> >&);
  304. // generated by autoexplicit.sh
  305. 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> >&);
  306. 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> >&);
  307. template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, 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> >&);
  308. 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> >&);
  309. 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> > > > > >&);
  310. 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> > > > > >&);
  311. #ifdef WIN32
  312. 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>>>>>> &);
  313. 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>>>>>> &);
  314. #endif
  315. 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> > > > > >&);
  316. 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> > > > > >&);
  317. #endif