polygons_to_triangles.cpp 8.3 KB

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