wire_mesh.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #include "wire_mesh.h"
  2. #include "../../list_to_matrix.h"
  3. #include "../../slice.h"
  4. #include "convex_hull.h"
  5. #include "mesh_boolean.h"
  6. #include <Eigen/Geometry>
  7. #include <vector>
  8. template <
  9. typename DerivedWV,
  10. typename DerivedWE,
  11. typename DerivedV,
  12. typename DerivedF,
  13. typename DerivedJ>
  14. IGL_INLINE void igl::copyleft::cgal::wire_mesh(
  15. const Eigen::MatrixBase<DerivedWV> & WV,
  16. const Eigen::MatrixBase<DerivedWE> & WE,
  17. const double th,
  18. const int poly_size,
  19. const bool solid,
  20. Eigen::PlainObjectBase<DerivedV> & V,
  21. Eigen::PlainObjectBase<DerivedF> & F,
  22. Eigen::PlainObjectBase<DerivedJ> & J)
  23. {
  24. typedef typename DerivedWV::Scalar Scalar;
  25. // Canonical polygon to place at each endpoint
  26. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3> MatrixX3S;
  27. MatrixX3S PV(poly_size,3);
  28. for(int p =0;p<PV.rows();p++)
  29. {
  30. const Scalar phi = (Scalar(p)/Scalar(PV.rows()))*2.*M_PI;
  31. PV(p,0) = 0.5*cos(phi);
  32. PV(p,1) = 0.5*sin(phi);
  33. PV(p,2) = 0;
  34. }
  35. V.resize(WV.rows() + PV.rows() * 2 * WE.rows(),3);
  36. V.topLeftCorner(WV.rows(),3) = WV;
  37. // Signed adjacency list
  38. std::vector<std::vector<std::pair<int,int> > > A(WV.rows());
  39. // Inputs:
  40. // e index of edge
  41. // c index of endpoint [0,1]
  42. // p index of polygon vertex
  43. // Returns index of corresponding vertex in V
  44. const auto index =
  45. [&PV,&WV](const int e, const int c, const int p)->int
  46. {
  47. return WV.rows() + e*2*PV.rows() + PV.rows()*c + p;
  48. };
  49. const auto unindex =
  50. [&PV,&WV](int v, int & e, int & c, int & p)
  51. {
  52. assert(v>=WV.rows());
  53. v = v-WV.rows();
  54. e = v/(2*PV.rows());
  55. v = v-e*(2*PV.rows());
  56. c = v/(PV.rows());
  57. v = v-c*(PV.rows());
  58. p = v;
  59. };
  60. // loop over all edges
  61. for(int e = 0;e<WE.rows();e++)
  62. {
  63. // Fill in adjacency list as we go
  64. A[WE(e,0)].emplace_back(e,0);
  65. A[WE(e,1)].emplace_back(e,1);
  66. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  67. const RowVector3S ev = WV.row(WE(e,1))-WV.row(WE(e,0));
  68. const RowVector3S uv = ev.normalized();
  69. Eigen::Quaternion<Scalar> q;
  70. q = q.FromTwoVectors(RowVector3S(0,0,1),uv);
  71. // loop over polygon vertices
  72. for(int p = 0;p<PV.rows();p++)
  73. {
  74. RowVector3S qp = q*(PV.row(p)*th);
  75. // loop over endpoints
  76. for(int c = 0;c<2;c++)
  77. {
  78. // Move to endpoint, offset by factor of thickness
  79. V.row(index(e,c,p)) =
  80. qp+WV.row(WE(e,c)) + 1.*th*Scalar(1-2*c)*uv;
  81. }
  82. }
  83. }
  84. std::vector<std::vector<typename DerivedF::Index> > vF;
  85. std::vector<int> vJ;
  86. const auto append_hull =
  87. [&V,&vF,&vJ,&unindex,&WV](const Eigen::VectorXi & I, const int j)
  88. {
  89. MatrixX3S Vv;
  90. igl::slice(V,I,1,Vv);
  91. Eigen::MatrixXi Fv;
  92. convex_hull(Vv,Fv);
  93. for(int f = 0;f<Fv.rows();f++)
  94. {
  95. const Eigen::Array<int,1,3> face(I(Fv(f,0)), I(Fv(f,1)), I(Fv(f,2)));
  96. //const bool on_vertex = (face<WV.rows()).any();
  97. //if(!on_vertex)
  98. //{
  99. // // This correctly prunes fcaes on the "caps" of convex hulls around
  100. // // edges, but for convex hulls around vertices this will only work if
  101. // // the incoming edges are not overlapping.
  102. // //
  103. // // Q: For convex hulls around vertices, is the correct thing to do:
  104. // // check if all corners of face lie *on or _outside_* of plane of "cap"?
  105. // //
  106. // // H: Maybe, but if there's an intersection then the boundary of the
  107. // // incoming convex hulls around edges is still not going to match up
  108. // // with the boundary on the convex hull around the vertices.
  109. // //
  110. // // Might have to bite the bullet and always call self-union.
  111. // bool all_same = true;
  112. // int e0,c0,p0;
  113. // unindex(face(0),e0,c0,p0);
  114. // for(int i = 1;i<3;i++)
  115. // {
  116. // int ei,ci,pi;
  117. // unindex(face(i),ei,ci,pi);
  118. // all_same = all_same && (e0==ei && c0==ci);
  119. // }
  120. // if(all_same)
  121. // {
  122. // // don't add this face
  123. // continue;
  124. // }
  125. //}
  126. vF.push_back( { face(0),face(1),face(2)});
  127. vJ.push_back(j);
  128. }
  129. };
  130. // loop over each vertex
  131. for(int v = 0;v<WV.rows();v++)
  132. {
  133. // Gather together this vertex and the polygon vertices of all incident
  134. // edges
  135. Eigen::VectorXi I(1+A[v].size()*PV.rows());
  136. // This vertex
  137. I(0) = v;
  138. for(int n = 0;n<A[v].size();n++)
  139. {
  140. for(int p = 0;p<PV.rows();p++)
  141. {
  142. const int e = A[v][n].first;
  143. const int c = A[v][n].second;
  144. I(1+n*PV.rows()+p) = index(e,c,p);
  145. }
  146. }
  147. append_hull(I,v);
  148. }
  149. // loop over each edge
  150. for(int e = 0;e<WE.rows();e++)
  151. {
  152. // Gether together polygon vertices of both endpoints
  153. Eigen::VectorXi I(PV.rows()*2);
  154. for(int c = 0;c<2;c++)
  155. {
  156. for(int p = 0;p<PV.rows();p++)
  157. {
  158. I(c*PV.rows()+p) = index(e,c,p);
  159. }
  160. }
  161. append_hull(I,WV.rows()+e);
  162. }
  163. list_to_matrix(vF,F);
  164. if(solid)
  165. {
  166. // Self-union to clean up
  167. igl::copyleft::cgal::mesh_boolean(
  168. Eigen::MatrixXd(V),Eigen::MatrixXi(F),Eigen::MatrixXd(),Eigen::MatrixXi(),
  169. "union",
  170. V,F,J);
  171. for(int j=0;j<J.size();j++) J(j) = vJ[J(j)];
  172. }else
  173. {
  174. list_to_matrix(vJ,J);
  175. }
  176. }
  177. template <
  178. typename DerivedWV,
  179. typename DerivedWE,
  180. typename DerivedV,
  181. typename DerivedF,
  182. typename DerivedJ>
  183. IGL_INLINE void igl::copyleft::cgal::wire_mesh(
  184. const Eigen::MatrixBase<DerivedWV> & WV,
  185. const Eigen::MatrixBase<DerivedWE> & WE,
  186. const double th,
  187. const int poly_size,
  188. Eigen::PlainObjectBase<DerivedV> & V,
  189. Eigen::PlainObjectBase<DerivedF> & F,
  190. Eigen::PlainObjectBase<DerivedJ> & J)
  191. {
  192. return wire_mesh(WV,WE,th,poly_size,true,V,F,J);
  193. }
  194. #ifdef IGL_STATIC_LIBRARY
  195. // Explicit template instantiation
  196. template void igl::copyleft::cgal::wire_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -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<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, double, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  197. #endif