triangle_triangle_adjacency.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. 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. template <
  240. typename DerivedEMAP,
  241. typename DeriveduEC,
  242. typename DeriveduEE,
  243. typename TTIndex,
  244. typename TTiIndex>
  245. IGL_INLINE void igl::triangle_triangle_adjacency(
  246. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  247. const Eigen::MatrixBase<DeriveduEC> & uEC,
  248. const Eigen::MatrixBase<DeriveduEE> & uEE,
  249. const bool construct_TTi,
  250. std::vector<std::vector<std::vector<TTIndex> > > & TT,
  251. std::vector<std::vector<std::vector<TTiIndex> > > & TTi)
  252. {
  253. using namespace std;
  254. using namespace Eigen;
  255. typedef Eigen::Index Index;
  256. const size_t m = EMAP.rows()/3;
  257. assert((size_t)EMAP.rows() == m*3 && "EMAP should come from list of triangles.");
  258. // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
  259. // and k
  260. TT.resize (m,vector<vector<TTIndex> >(3));
  261. if(construct_TTi)
  262. {
  263. TTi.resize(m,vector<vector<TTiIndex> >(3));
  264. }
  265. // No race conditions because TT*[f][c]'s are in bijection with e's
  266. // Minimum number of items per thread
  267. //const size_t num_e = E.rows();
  268. // Slightly better memory access than loop over E
  269. igl::parallel_for(
  270. m,
  271. [&](const Index & f)
  272. {
  273. for(Index c = 0;c<3;c++)
  274. {
  275. const Index e = f + m*c;
  276. //const Index c = e/m;
  277. //const vector<uE2EType> & N = uE2E[EMAP(e)];
  278. //for(const auto & ne : N)
  279. for(Index j = uEC(EMAP(e));j<uEC(EMAP(e)+1);j++)
  280. {
  281. const auto ne = uEE(j);
  282. const Index nf = ne%m;
  283. // don't add self
  284. if(nf != f)
  285. {
  286. TT[f][c].push_back(nf);
  287. if(construct_TTi)
  288. {
  289. const Index nc = ne/m;
  290. TTi[f][c].push_back(nc);
  291. }
  292. }
  293. }
  294. }
  295. },
  296. 1000ul);
  297. }
  298. #ifdef IGL_STATIC_LIBRARY
  299. // Explicit template instantiation
  300. // generated by autoexplicit.sh
  301. 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> > > > > >&);
  302. // generated by autoexplicit.sh
  303. 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> >&);
  304. // generated by autoexplicit.sh
  305. 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> > > > > >&);
  306. // generated by autoexplicit.sh
  307. 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> >&);
  308. // generated by autoexplicit.sh
  309. 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> >&);
  310. 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> >&);
  311. 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> >&);
  312. 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> >&);
  313. 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> > > > > >&);
  314. 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> > > > > >&);
  315. #ifdef WIN32
  316. 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>>>>>> &);
  317. 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>>>>>> &);
  318. #endif
  319. 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> > > > > >&);
  320. 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> > > > > >&);
  321. #endif