order_facets_around_edges.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include "order_facets_around_edges.h"
  2. #include <type_traits>
  3. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  4. template<
  5. typename DerivedV,
  6. typename DerivedF,
  7. typename DerivedN,
  8. typename DerivedE,
  9. typename DeriveduE,
  10. typename DerivedEMAP,
  11. typename uE2EType,
  12. typename uE2oEType,
  13. typename uE2CType >
  14. IGL_INLINE
  15. typename std::enable_if<!std::is_same<typename DerivedV::Scalar,
  16. typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
  17. igl::order_facets_around_edges(
  18. const Eigen::PlainObjectBase<DerivedV>& V,
  19. const Eigen::PlainObjectBase<DerivedF>& F,
  20. const Eigen::PlainObjectBase<DerivedN>& N,
  21. const Eigen::PlainObjectBase<DerivedE>& E,
  22. const Eigen::PlainObjectBase<DeriveduE>& uE,
  23. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  24. const std::vector<std::vector<uE2EType> >& uE2E,
  25. std::vector<std::vector<uE2oEType> >& uE2oE,
  26. std::vector<std::vector<uE2CType > >& uE2C ) {
  27. typedef Eigen::Matrix<typename DerivedN::Scalar, 3, 1> Vector3F;
  28. const typename DerivedV::Scalar EPS = 1e-12;
  29. const size_t num_faces = F.rows();
  30. const size_t num_undirected_edges = uE.rows();
  31. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  32. auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
  33. uE2oE.resize(num_undirected_edges);
  34. uE2C.resize(num_undirected_edges);
  35. for(size_t ui = 0;ui<num_undirected_edges;ui++)
  36. {
  37. const auto& adj_edges = uE2E[ui];
  38. const size_t edge_valance = adj_edges.size();
  39. assert(edge_valance > 0);
  40. const auto ref_edge = adj_edges[0];
  41. const auto ref_face = edge_index_to_face_index(ref_edge);
  42. Vector3F ref_normal = N.row(ref_face);
  43. const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
  44. const auto ref_corner_s = (ref_corner_o+1)%3;
  45. const auto ref_corner_d = (ref_corner_o+2)%3;
  46. const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
  47. const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
  48. const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
  49. Vector3F edge = V.row(d) - V.row(s);
  50. auto edge_len = edge.norm();
  51. bool degenerated = edge_len < EPS;
  52. if (degenerated) {
  53. if (edge_valance <= 2) {
  54. // There is only one way to order 2 or less faces.
  55. edge.setZero();
  56. } else {
  57. edge.setZero();
  58. Eigen::Matrix<typename DerivedN::Scalar, Eigen::Dynamic, 3>
  59. normals(edge_valance, 3);
  60. for (size_t fei=0; fei<edge_valance; fei++) {
  61. const auto fe = adj_edges[fei];
  62. const auto f = edge_index_to_face_index(fe);
  63. normals.row(fei) = N.row(f);
  64. }
  65. for (size_t i=0; i<edge_valance; i++) {
  66. size_t j = (i+1) % edge_valance;
  67. Vector3F ni = normals.row(i);
  68. Vector3F nj = normals.row(j);
  69. edge = ni.cross(nj);
  70. edge_len = edge.norm();
  71. if (edge_len >= EPS) {
  72. edge.normalize();
  73. break;
  74. }
  75. }
  76. // Ensure edge direction are consistent with reference face.
  77. Vector3F in_face_vec = V.row(o) - V.row(s);
  78. if (edge.cross(in_face_vec).dot(ref_normal) < 0) {
  79. edge *= -1;
  80. }
  81. if (edge.norm() < EPS) {
  82. std::cerr << "=====================================" << std::endl;
  83. std::cerr << " ui: " << ui << std::endl;
  84. std::cerr << "edge: " << ref_edge << std::endl;
  85. std::cerr << "face: " << ref_face << std::endl;
  86. std::cerr << " vs: " << V.row(s) << std::endl;
  87. std::cerr << " vd: " << V.row(d) << std::endl;
  88. std::cerr << "adj face normals: " << std::endl;
  89. std::cerr << normals << std::endl;
  90. std::cerr << "Very degenerated case detected:" << std::endl;
  91. std::cerr << "Near zero edge surrounded by "
  92. << edge_valance << " neearly colinear faces" <<
  93. std::endl;
  94. std::cerr << "=====================================" << std::endl;
  95. }
  96. }
  97. } else {
  98. edge.normalize();
  99. }
  100. Eigen::MatrixXd angle_data(edge_valance, 3);
  101. std::vector<bool> cons(edge_valance);
  102. for (size_t fei=0; fei<edge_valance; fei++) {
  103. const auto fe = adj_edges[fei];
  104. const auto f = edge_index_to_face_index(fe);
  105. const auto c = edge_index_to_corner_index(fe);
  106. cons[fei] = (d == F(f, (c+1)%3));
  107. assert( cons[fei] || (d == F(f,(c+2)%3)));
  108. assert(!cons[fei] || (s == F(f,(c+2)%3)));
  109. assert(!cons[fei] || (d == F(f,(c+1)%3)));
  110. Vector3F n = N.row(f);
  111. angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
  112. angle_data(fei, 1) = ref_normal.dot(n);
  113. if (cons[fei]) {
  114. angle_data(fei, 0) *= -1;
  115. angle_data(fei, 1) *= -1;
  116. }
  117. angle_data(fei, 0) *= -1; // Sort clockwise.
  118. angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
  119. }
  120. Eigen::VectorXi order;
  121. igl::sort_angles(angle_data, order);
  122. auto& ordered_edges = uE2oE[ui];
  123. auto& consistency = uE2C[ui];
  124. ordered_edges.resize(edge_valance);
  125. consistency.resize(edge_valance);
  126. for (size_t fei=0; fei<edge_valance; fei++) {
  127. ordered_edges[fei] = adj_edges[order[fei]];
  128. consistency[fei] = cons[order[fei]];
  129. }
  130. }
  131. }
  132. template<
  133. typename DerivedV,
  134. typename DerivedF,
  135. typename DerivedN,
  136. typename DerivedE,
  137. typename DeriveduE,
  138. typename DerivedEMAP,
  139. typename uE2EType,
  140. typename uE2oEType,
  141. typename uE2CType >
  142. IGL_INLINE
  143. typename std::enable_if<std::is_same<typename DerivedV::Scalar,
  144. typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
  145. igl::order_facets_around_edges(
  146. const Eigen::PlainObjectBase<DerivedV>& V,
  147. const Eigen::PlainObjectBase<DerivedF>& F,
  148. const Eigen::PlainObjectBase<DerivedN>& N,
  149. const Eigen::PlainObjectBase<DerivedE>& E,
  150. const Eigen::PlainObjectBase<DeriveduE>& uE,
  151. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  152. const std::vector<std::vector<uE2EType> >& uE2E,
  153. std::vector<std::vector<uE2oEType> >& uE2oE,
  154. std::vector<std::vector<uE2CType > >& uE2C ) {
  155. typedef Eigen::Matrix<typename DerivedN::Scalar, 3, 1> Vector3F;
  156. typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
  157. const typename DerivedV::Scalar EPS = 1e-12;
  158. const size_t num_faces = F.rows();
  159. const size_t num_undirected_edges = uE.rows();
  160. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  161. auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
  162. uE2oE.resize(num_undirected_edges);
  163. uE2C.resize(num_undirected_edges);
  164. for(size_t ui = 0;ui<num_undirected_edges;ui++)
  165. {
  166. const auto& adj_edges = uE2E[ui];
  167. const size_t edge_valance = adj_edges.size();
  168. assert(edge_valance > 0);
  169. const auto ref_edge = adj_edges[0];
  170. const auto ref_face = edge_index_to_face_index(ref_edge);
  171. Vector3F ref_normal = N.row(ref_face);
  172. const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
  173. const auto ref_corner_s = (ref_corner_o+1)%3;
  174. const auto ref_corner_d = (ref_corner_o+2)%3;
  175. const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
  176. const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
  177. const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
  178. Vector3E exact_edge = V.row(d) - V.row(s);
  179. exact_edge.array() /= exact_edge.squaredNorm();
  180. Vector3F edge(
  181. CGAL::to_double(exact_edge[0]),
  182. CGAL::to_double(exact_edge[1]),
  183. CGAL::to_double(exact_edge[2]));
  184. edge.normalize();
  185. Eigen::MatrixXd angle_data(edge_valance, 3);
  186. std::vector<bool> cons(edge_valance);
  187. for (size_t fei=0; fei<edge_valance; fei++) {
  188. const auto fe = adj_edges[fei];
  189. const auto f = edge_index_to_face_index(fe);
  190. const auto c = edge_index_to_corner_index(fe);
  191. cons[fei] = (d == F(f, (c+1)%3));
  192. assert( cons[fei] || (d == F(f,(c+2)%3)));
  193. assert(!cons[fei] || (s == F(f,(c+2)%3)));
  194. assert(!cons[fei] || (d == F(f,(c+1)%3)));
  195. Vector3F n = N.row(f);
  196. angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
  197. angle_data(fei, 1) = ref_normal.dot(n);
  198. if (cons[fei]) {
  199. angle_data(fei, 0) *= -1;
  200. angle_data(fei, 1) *= -1;
  201. }
  202. angle_data(fei, 0) *= -1; // Sort clockwise.
  203. angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
  204. }
  205. Eigen::VectorXi order;
  206. igl::sort_angles(angle_data, order);
  207. auto& ordered_edges = uE2oE[ui];
  208. auto& consistency = uE2C[ui];
  209. ordered_edges.resize(edge_valance);
  210. consistency.resize(edge_valance);
  211. for (size_t fei=0; fei<edge_valance; fei++) {
  212. ordered_edges[fei] = adj_edges[order[fei]];
  213. consistency[fei] = cons[order[fei]];
  214. }
  215. }
  216. }