outer_hull.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include "outer_hull.h"
  2. #include "outer_facet.h"
  3. #include "facet_components.h"
  4. #include "triangle_triangle_adjacency.h"
  5. #include "unique_edge_map.h"
  6. #include "per_face_normals.h"
  7. #include "all_edges.h"
  8. #include "colon.h"
  9. #include "get_seconds.h"
  10. #include <Eigen/Geometry>
  11. #include <vector>
  12. #include <map>
  13. #include <queue>
  14. #include <iostream>
  15. template <
  16. typename DerivedV,
  17. typename DerivedF,
  18. typename DerivedG,
  19. typename DerivedJ,
  20. typename Derivedflip>
  21. IGL_INLINE void igl::outer_hull(
  22. const Eigen::PlainObjectBase<DerivedV> & V,
  23. const Eigen::PlainObjectBase<DerivedF> & F,
  24. Eigen::PlainObjectBase<DerivedG> & G,
  25. Eigen::PlainObjectBase<DerivedJ> & J,
  26. Eigen::PlainObjectBase<Derivedflip> & flip)
  27. {
  28. using namespace Eigen;
  29. using namespace std;
  30. using namespace igl;
  31. typedef typename DerivedF::Index Index;
  32. Matrix<Index,DerivedF::RowsAtCompileTime,1> C;
  33. typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
  34. typedef Matrix<typename DerivedG::Scalar,Dynamic,DerivedG::ColsAtCompileTime> MatrixXG;
  35. typedef Matrix<typename DerivedJ::Scalar,Dynamic,DerivedJ::ColsAtCompileTime> MatrixXJ;
  36. typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
  37. const Index m = F.rows();
  38. typedef Matrix<typename DerivedF::Scalar,Dynamic,2> MatrixX2I;
  39. typedef Matrix<typename DerivedF::Index,Dynamic,1> VectorXI;
  40. MatrixX2I E,uE;
  41. VectorXI EMAP;
  42. vector<vector<typename DerivedF::Index> > uE2E;
  43. unique_edge_map(F,E,uE,EMAP,uE2E);
  44. vector<vector<vector<Index > > > TT,_1;
  45. triangle_triangle_adjacency(E,EMAP,uE2E,false,TT,_1);
  46. facet_components(TT,C);
  47. const Index ncc = C.maxCoeff()+1;
  48. G.resize(0,F.cols());
  49. J.resize(0,1);
  50. flip.setConstant(m,1,false);
  51. // precompute face normals
  52. typename Eigen::Matrix<
  53. typename DerivedV::Scalar,
  54. DerivedF::RowsAtCompileTime,
  55. 3> N;
  56. per_face_normals(V,F,N);
  57. // H contains list of faces on outer hull;
  58. vector<bool> FH(m,false);
  59. vector<bool> EH(3*m,false);
  60. vector<MatrixXG> vG(ncc);
  61. vector<MatrixXJ> vJ(ncc);
  62. // Total size of G (and J)
  63. size_t nG = 0;
  64. // This is O( (n+m) * nnc) !
  65. for(Index id = 0;id<ncc;id++)
  66. {
  67. // Determine number of facets in component id
  68. Index num_id = 0;
  69. for(Index f = 0;f<m;f++)
  70. {
  71. if(C(f) == id)
  72. {
  73. num_id++;
  74. }
  75. }
  76. //MatrixXF Fc(num_id,F.cols());
  77. MatrixXJ IM(num_id,1);
  78. if(C.maxCoeff() == 0)
  79. {
  80. assert(num_id == F.rows());
  81. //Fc = F;
  82. IM = MatrixXJ::LinSpaced(F.rows(),0,F.rows()-1);
  83. }else
  84. {
  85. int g = 0;
  86. for(Index f = 0;f<m;f++)
  87. {
  88. if(C(f) == id)
  89. {
  90. //Fc.row(g) = F.row(f);
  91. IM(g) = f;
  92. g++;
  93. }
  94. }
  95. }
  96. {
  97. // starting face that's guaranteed to be on the outer hull and in this
  98. // component
  99. int f;
  100. bool f_flip;
  101. outer_facet(V,F,N,IM,f,f_flip);
  102. // Q contains list of face edges to continue traversing upong
  103. queue<int> Q;
  104. Q.push(f+0*m);
  105. Q.push(f+1*m);
  106. Q.push(f+2*m);
  107. flip[f] = f_flip;
  108. int FHcount = 0;
  109. while(!Q.empty())
  110. {
  111. // face-edge
  112. const int e = Q.front();
  113. Q.pop();
  114. // face
  115. const int f = e%m;
  116. // corner
  117. const int c = e/m;
  118. // Should never see edge again...
  119. if(EH[e] == true)
  120. {
  121. continue;
  122. }
  123. EH[e] = true;
  124. // first time seeing face
  125. if(!FH[f])
  126. {
  127. FH[f] = true;
  128. FHcount++;
  129. }
  130. // find overlapping face-edges
  131. const auto & neighbors = uE2E[EMAP(e)];
  132. const auto & fN = (flip[f]?-1.:1.)*N.row(f);
  133. // source of edge according to f
  134. const int fs = flip[f]?F(f,(c+2)%3):F(f,(c+1)%3);
  135. // destination of edge according to f
  136. const int fd = flip[f]?F(f,(c+1)%3):F(f,(c+2)%3);
  137. const auto & eV = (V.row(fd)-V.row(fs)).normalized();
  138. // Loop over and find max dihedral angle
  139. typename DerivedV::Scalar max_di = -1;
  140. int max_ne = -1;
  141. typename Eigen::Matrix< typename DerivedV::Scalar, 1, 3> max_nN;
  142. for(const auto & ne : neighbors)
  143. {
  144. const int nf = ne%m;
  145. if(nf == f)
  146. {
  147. continue;
  148. }
  149. const int nc = ne/m;
  150. // are faces consistently oriented
  151. //const int ns = F(nf,(nc+1)%3);
  152. const int nd = F(nf,(nc+2)%3);
  153. const bool cons = (flip[f]?fd:fs) == nd;
  154. const auto & nN = (cons? (flip[f]?-1:1.) : (flip[f]?1.:-1.) )*N.row(nf);
  155. const auto & ndi = M_PI - atan2( fN.cross(nN).dot(eV), fN.dot(nN));
  156. if(ndi>=max_di)
  157. {
  158. max_ne = ne;
  159. max_di = ndi;
  160. max_nN = nN;
  161. }
  162. }
  163. if(max_ne>=0)
  164. {
  165. const int nf = max_ne%m;
  166. const int nc = max_ne/m;
  167. const int nd = F(nf,(nc+2)%3);
  168. const bool cons = (flip[f]?fd:fs) == nd;
  169. flip[nf] = (cons ? flip[f] : !flip[f]);
  170. const int ne1 = nf+((nc+1)%3)*m;
  171. const int ne2 = nf+((nc+2)%3)*m;
  172. if(!EH[ne1])
  173. {
  174. Q.push(ne1);
  175. }
  176. if(!EH[ne2])
  177. {
  178. Q.push(ne2);
  179. }
  180. }
  181. }
  182. {
  183. vG[id].resize(FHcount,3);
  184. vJ[id].resize(FHcount,1);
  185. nG += FHcount;
  186. size_t h = 0;
  187. for(int i = 0;i<num_id;i++)
  188. {
  189. const size_t f = IM(i);
  190. //if(f_flip)
  191. //{
  192. // flip[f] = !flip[f];
  193. //}
  194. if(FH[f])
  195. {
  196. vG[id].row(h) = (flip[f]?F.row(f).reverse().eval():F.row(f));
  197. vJ[id](h,0) = f;
  198. h++;
  199. }
  200. }
  201. assert(h == FHcount);
  202. }
  203. }
  204. }
  205. // collect G and J across components
  206. G.resize(nG,3);
  207. J.resize(nG,1);
  208. {
  209. size_t off = 0;
  210. for(Index id = 0;id<ncc;id++)
  211. {
  212. assert(vG[id].rows() == vJ[id].rows());
  213. G.block(off,0,vG[id].rows(),vG[id].cols()) = vG[id];
  214. J.block(off,0,vJ[id].rows(),vJ[id].cols()) = vJ[id];
  215. off += vG[id].rows();
  216. }
  217. }
  218. }
  219. #ifdef IGL_STATIC_LIBRARY
  220. // Explicit template specialization
  221. template void igl::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
  222. #endif