polygons_to_triangles.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include "polygons_to_triangles.h"
  2. #include "ear_clipping.h"
  3. #include "../sort.h"
  4. #include "../placeholders.h"
  5. #include <Eigen/Eigenvalues>
  6. template <
  7. typename DerivedV,
  8. typename DerivedI,
  9. typename DerivedC,
  10. typename DerivedF,
  11. typename DerivedJ>
  12. IGL_INLINE void igl::predicates::polygons_to_triangles(
  13. const Eigen::MatrixBase<DerivedV> & V,
  14. const Eigen::MatrixBase<DerivedI> & I,
  15. const Eigen::MatrixBase<DerivedC> & C,
  16. Eigen::PlainObjectBase<DerivedF> & F,
  17. Eigen::PlainObjectBase<DerivedJ> & J)
  18. {
  19. typedef Eigen::Index Index;
  20. // Each polygon results in #sides-2 triangles. So ∑#sides-2
  21. F.resize(C(C.size()-1) - (C.size()-1)*2,3);
  22. J.resize(F.rows());
  23. {
  24. Index f = 0;
  25. for(Index p = 0;p<C.size()-1;p++)
  26. {
  27. const Index np = C(p+1)-C(p);
  28. Eigen::MatrixXi pF;
  29. if(np == 3)
  30. {
  31. pF = (Eigen::MatrixXi(1,3)<<0,1,2).finished();
  32. }else
  33. {
  34. // Make little copy of this polygon with an initial fan
  35. DerivedV pV(np,V.cols());
  36. for(Index c = 0;c<np;c++)
  37. {
  38. pV.row(c) = V.row(I(C(p)+c));
  39. }
  40. // Use PCA to project to 2D
  41. Eigen::MatrixXd S;
  42. switch(V.cols())
  43. {
  44. case 2:
  45. S = V.template cast<double>();
  46. break;
  47. case 3:
  48. {
  49. Eigen::MatrixXd P = (pV.rowwise() - pV.colwise().mean()).template cast<double>();
  50. Eigen::Matrix3d O = P.transpose() * P;
  51. Eigen::EigenSolver<Eigen::Matrix3d> es(O);
  52. Eigen::Matrix3d C = es.eigenvectors().real();
  53. {
  54. Eigen::Vector3d _1;
  55. Eigen::Vector3i I;
  56. igl::sort(es.eigenvalues().real().eval(),1,false,_1,I);
  57. C = C(igl::placeholders::all,I).eval();
  58. }
  59. S = P*C.leftCols(2);
  60. break;
  61. }
  62. default: assert(false && "dim>3 not supported");
  63. }
  64. Eigen::VectorXi RT = Eigen::VectorXi::Zero(S.rows(),1);
  65. Eigen::VectorXi _I;
  66. Eigen::MatrixXd _nS;
  67. // compute signed area
  68. {
  69. double area = 0;
  70. for(Index c = 0;c<np;c++)
  71. {
  72. area += S((c+0)%np,0)*S((c+1)%np,1) - S((c+1)%np,0)*S((c+0)%np,1);
  73. }
  74. //prIndexf("area: %g\n",area);
  75. if(area<0)
  76. {
  77. S.col(0) *= -1;
  78. }
  79. }
  80. // This is a really low quality triangulator and will contain nearly
  81. // degenerate elements which become degenerate or worse when unprojected
  82. // back to 3D.
  83. // igl::predicates::ear_clipping does not gracefully fail when the input
  84. // is not simple. Instead it (tends?) to output too few triangles.
  85. if(! igl::predicates::ear_clipping(S,pF) )
  86. {
  87. // Fallback, use a fan
  88. //std::cout<<igl::matlab_format(S,"S")<<std::endl;
  89. //std::cout<<igl::matlab_format(RT,"RT")<<std::endl;
  90. //std::cout<<igl::matlab_format(_I,"I")<<std::endl;
  91. //std::cout<<igl::matlab_format(pF,"pF")<<std::endl;
  92. //std::cout<<igl::matlab_format(_nS,"nS")<<std::endl;
  93. //std::cout<<std::endl;
  94. pF.resize(np-2,3);
  95. for(Index c = 0;c<np;c++)
  96. {
  97. if(c>0 && c<np-1)
  98. {
  99. pF(c-1,0) = 0;
  100. pF(c-1,1) = c;
  101. pF(c-1,2) = c+1;
  102. }
  103. }
  104. }
  105. assert(pF.rows() == np-2);
  106. // Could at least flip edges of degenerate edges
  107. //if(pF.rows()>1)
  108. //{
  109. // // Delaunay-ize
  110. // Eigen::MatrixXd pl;
  111. // igl::edge_lengths(pV,pF,pl);
  112. // typedef Eigen::Matrix<Index,Eigen::Dynamic,2> MatrixX2I;
  113. // typedef Eigen::Matrix<Index,Eigen::Dynamic,1> VectorXI;
  114. // MatrixX2I E,uE;
  115. // VectorXI EMAP;
  116. // std::vector<std::vector<Index> > uE2E;
  117. // igl::unique_edge_map(pF, E, uE, EMAP, uE2E);
  118. // typedef Index Index;
  119. // typedef double Scalar;
  120. // const Index num_faces = pF.rows();
  121. // std::vector<Index> Q;
  122. // Q.reserve(uE2E.size());
  123. // for (size_t uei=0; uei<uE2E.size(); uei++)
  124. // {
  125. // Q.push_back(uei);
  126. // }
  127. // while(!Q.empty())
  128. // {
  129. // const Index uei = Q.back();
  130. // Q.pop_back();
  131. // if (uE2E[uei].size() == 2)
  132. // {
  133. // double w;
  134. // igl::is_Indexrinsic_delaunay(pl,uE2E,num_faces,uei,w);
  135. // prIndexf("%d : %0.17f\n",uei,w);
  136. // if(w<-1e-7)
  137. // {
  138. // prIndexf(" flippin'\n");
  139. // //
  140. // // v1 v1
  141. // // /|\ / \
  142. // // c/ | \b c/f1 \b
  143. // // v3 /f2|f1\ v4 => v3 /__f__\ v4
  144. // // \ e / \ f2 /
  145. // // d\ | /a d\ /a
  146. // // \|/ \ /
  147. // // v2 v2
  148. // //
  149. // // hmm... is the flip actually in the other direction?
  150. // const Index f1 = uE2E[uei][0]%num_faces;
  151. // const Index f2 = uE2E[uei][1]%num_faces;
  152. // const Index c1 = uE2E[uei][0]/num_faces;
  153. // const Index c2 = uE2E[uei][1]/num_faces;
  154. // const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
  155. // const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
  156. // const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
  157. // const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
  158. // const size_t ue_24 = EMAP(e_24);
  159. // const size_t ue_41 = EMAP(e_41);
  160. // const size_t ue_13 = EMAP(e_13);
  161. // const size_t ue_32 = EMAP(e_32);
  162. // // new edge lengths
  163. // const Index v1 = pF(f1, (c1+1)%3);
  164. // const Index v2 = pF(f1, (c1+2)%3);
  165. // const Index v4 = pF(f1, c1);
  166. // const Index v3 = pF(f2, c2);
  167. // {
  168. // const Scalar e = pl(f1,c1);
  169. // const Scalar a = pl(f1,(c1+1)%3);
  170. // const Scalar b = pl(f1,(c1+2)%3);
  171. // const Scalar c = pl(f2,(c2+1)%3);
  172. // const Scalar d = pl(f2,(c2+2)%3);
  173. // const double f = (pV.row(v3)-pV.row(v4)).norm();
  174. // // New order
  175. // pl(f1,0) = f;
  176. // pl(f1,1) = b;
  177. // pl(f1,2) = c;
  178. // pl(f2,0) = f;
  179. // pl(f2,1) = d;
  180. // pl(f2,2) = a;
  181. // }
  182. // prIndexf("%d,%d %d,%d -> %d,%d\n",uE(uei,0),uE(uei,1),v1,v2,v3,v4);
  183. // igl::flip_edge(pF, E, uE, EMAP, uE2E, uei);
  184. // std::cout<<" "<<pl.row(f1)<<std::endl;
  185. // std::cout<<" "<<pl.row(f2)<<std::endl;
  186. // //// new edge lengths, slow!
  187. // //igl::edge_lengths(pV,pF,pl);
  188. // // recompute edge lengths of two faces. (extra work on untouched
  189. // // edges)
  190. // for(Index f : {f1,f2})
  191. // {
  192. // for(Index c=0;c<3;c++)
  193. // {
  194. // pl(f,c) =
  195. // (pV.row(pF(f,(c+1)%3))-pV.row(pF(f,(c+2)%3))).norm();
  196. // }
  197. // }
  198. // std::cout<<" "<<pl.row(f1)<<std::endl;
  199. // std::cout<<" "<<pl.row(f2)<<std::endl;
  200. // std::cout<<std::endl;
  201. // Q.push_back(ue_24);
  202. // Q.push_back(ue_41);
  203. // Q.push_back(ue_13);
  204. // Q.push_back(ue_32);
  205. // }
  206. // }
  207. // }
  208. // // check for self-loops (I claim these cannot happen)
  209. // for(Index f = 0;f<pF.rows();f++)
  210. // {
  211. // for(Index c =0;c<3;c++)
  212. // {
  213. // assert(pF(f,c) != pF(f,(c+1)%3) && "self loops should not exist");
  214. // }
  215. // }
  216. //}
  217. }
  218. // Copy Indexo global list
  219. for(Index i = 0;i<pF.rows();i++)
  220. {
  221. for(Index c =0;c<3;c++)
  222. {
  223. F(f,c) = I(C(p)+pF(i,c));
  224. }
  225. J(f) = p;
  226. f++;
  227. }
  228. }
  229. assert(f == F.rows());
  230. }
  231. }
  232. #ifdef IGL_STATIC_LIBRARY
  233. // Explicit template instantiation
  234. #endif