order_facets_around_edges.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "order_facets_around_edges.h"
  9. #include "order_facets_around_edge.h"
  10. #include "../sort_angles.h"
  11. #include <type_traits>
  12. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  13. template<
  14. typename DerivedV,
  15. typename DerivedF,
  16. typename DerivedN,
  17. typename DerivedE,
  18. typename DeriveduE,
  19. typename DerivedEMAP,
  20. typename uE2EType,
  21. typename uE2oEType,
  22. typename uE2CType >
  23. IGL_INLINE
  24. typename std::enable_if<!std::is_same<typename DerivedV::Scalar,
  25. typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
  26. igl::cgal::order_facets_around_edges(
  27. const Eigen::PlainObjectBase<DerivedV>& V,
  28. const Eigen::PlainObjectBase<DerivedF>& F,
  29. const Eigen::PlainObjectBase<DerivedN>& N,
  30. const Eigen::PlainObjectBase<DerivedE>& E,
  31. const Eigen::PlainObjectBase<DeriveduE>& uE,
  32. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  33. const std::vector<std::vector<uE2EType> >& uE2E,
  34. std::vector<std::vector<uE2oEType> >& uE2oE,
  35. std::vector<std::vector<uE2CType > >& uE2C ) {
  36. typedef Eigen::Matrix<typename DerivedN::Scalar, 3, 1> Vector3F;
  37. const typename DerivedV::Scalar EPS = 1e-12;
  38. const size_t num_faces = F.rows();
  39. const size_t num_undirected_edges = uE.rows();
  40. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  41. auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
  42. uE2oE.resize(num_undirected_edges);
  43. uE2C.resize(num_undirected_edges);
  44. for(size_t ui = 0;ui<num_undirected_edges;ui++)
  45. {
  46. const auto& adj_edges = uE2E[ui];
  47. const size_t edge_valance = adj_edges.size();
  48. assert(edge_valance > 0);
  49. const auto ref_edge = adj_edges[0];
  50. const auto ref_face = edge_index_to_face_index(ref_edge);
  51. Vector3F ref_normal = N.row(ref_face);
  52. const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
  53. const auto ref_corner_s = (ref_corner_o+1)%3;
  54. const auto ref_corner_d = (ref_corner_o+2)%3;
  55. const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
  56. const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
  57. const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
  58. Vector3F edge = V.row(d) - V.row(s);
  59. auto edge_len = edge.norm();
  60. bool degenerated = edge_len < EPS;
  61. if (degenerated) {
  62. if (edge_valance <= 2) {
  63. // There is only one way to order 2 or less faces.
  64. edge.setZero();
  65. } else {
  66. edge.setZero();
  67. Eigen::Matrix<typename DerivedN::Scalar, Eigen::Dynamic, 3>
  68. normals(edge_valance, 3);
  69. for (size_t fei=0; fei<edge_valance; fei++) {
  70. const auto fe = adj_edges[fei];
  71. const auto f = edge_index_to_face_index(fe);
  72. normals.row(fei) = N.row(f);
  73. }
  74. for (size_t i=0; i<edge_valance; i++) {
  75. size_t j = (i+1) % edge_valance;
  76. Vector3F ni = normals.row(i);
  77. Vector3F nj = normals.row(j);
  78. edge = ni.cross(nj);
  79. edge_len = edge.norm();
  80. if (edge_len >= EPS) {
  81. edge.normalize();
  82. break;
  83. }
  84. }
  85. // Ensure edge direction are consistent with reference face.
  86. Vector3F in_face_vec = V.row(o) - V.row(s);
  87. if (edge.cross(in_face_vec).dot(ref_normal) < 0) {
  88. edge *= -1;
  89. }
  90. if (edge.norm() < EPS) {
  91. std::cerr << "=====================================" << std::endl;
  92. std::cerr << " ui: " << ui << std::endl;
  93. std::cerr << "edge: " << ref_edge << std::endl;
  94. std::cerr << "face: " << ref_face << std::endl;
  95. std::cerr << " vs: " << V.row(s) << std::endl;
  96. std::cerr << " vd: " << V.row(d) << std::endl;
  97. std::cerr << "adj face normals: " << std::endl;
  98. std::cerr << normals << std::endl;
  99. std::cerr << "Very degenerated case detected:" << std::endl;
  100. std::cerr << "Near zero edge surrounded by "
  101. << edge_valance << " neearly colinear faces" <<
  102. std::endl;
  103. std::cerr << "=====================================" << std::endl;
  104. }
  105. }
  106. } else {
  107. edge.normalize();
  108. }
  109. Eigen::MatrixXd angle_data(edge_valance, 3);
  110. std::vector<bool> cons(edge_valance);
  111. for (size_t fei=0; fei<edge_valance; fei++) {
  112. const auto fe = adj_edges[fei];
  113. const auto f = edge_index_to_face_index(fe);
  114. const auto c = edge_index_to_corner_index(fe);
  115. cons[fei] = (d == F(f, (c+1)%3));
  116. assert( cons[fei] || (d == F(f,(c+2)%3)));
  117. assert(!cons[fei] || (s == F(f,(c+2)%3)));
  118. assert(!cons[fei] || (d == F(f,(c+1)%3)));
  119. Vector3F n = N.row(f);
  120. angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
  121. angle_data(fei, 1) = ref_normal.dot(n);
  122. if (cons[fei]) {
  123. angle_data(fei, 0) *= -1;
  124. angle_data(fei, 1) *= -1;
  125. }
  126. angle_data(fei, 0) *= -1; // Sort clockwise.
  127. angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
  128. }
  129. std::cout << "angle_data:" << std::endl;
  130. std::cout << angle_data << std::endl;
  131. Eigen::VectorXi order;
  132. igl::sort_angles(angle_data, order);
  133. std::cout << "order: " << order.transpose() << std::endl;
  134. auto& ordered_edges = uE2oE[ui];
  135. auto& consistency = uE2C[ui];
  136. ordered_edges.resize(edge_valance);
  137. consistency.resize(edge_valance);
  138. for (size_t fei=0; fei<edge_valance; fei++) {
  139. ordered_edges[fei] = adj_edges[order[fei]];
  140. consistency[fei] = cons[order[fei]];
  141. }
  142. }
  143. }
  144. template<
  145. typename DerivedV,
  146. typename DerivedF,
  147. typename DerivedN,
  148. typename DerivedE,
  149. typename DeriveduE,
  150. typename DerivedEMAP,
  151. typename uE2EType,
  152. typename uE2oEType,
  153. typename uE2CType >
  154. IGL_INLINE
  155. typename std::enable_if<std::is_same<typename DerivedV::Scalar,
  156. typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
  157. igl::cgal::order_facets_around_edges(
  158. const Eigen::PlainObjectBase<DerivedV>& V,
  159. const Eigen::PlainObjectBase<DerivedF>& F,
  160. const Eigen::PlainObjectBase<DerivedN>& N,
  161. const Eigen::PlainObjectBase<DerivedE>& E,
  162. const Eigen::PlainObjectBase<DeriveduE>& uE,
  163. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  164. const std::vector<std::vector<uE2EType> >& uE2E,
  165. std::vector<std::vector<uE2oEType> >& uE2oE,
  166. std::vector<std::vector<uE2CType > >& uE2C ) {
  167. typedef Eigen::Matrix<typename DerivedN::Scalar, 3, 1> Vector3F;
  168. typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
  169. const typename DerivedV::Scalar EPS = 1e-12;
  170. const size_t num_faces = F.rows();
  171. const size_t num_undirected_edges = uE.rows();
  172. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  173. auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
  174. uE2oE.resize(num_undirected_edges);
  175. uE2C.resize(num_undirected_edges);
  176. for(size_t ui = 0;ui<num_undirected_edges;ui++)
  177. {
  178. const auto& adj_edges = uE2E[ui];
  179. const size_t edge_valance = adj_edges.size();
  180. assert(edge_valance > 0);
  181. const auto ref_edge = adj_edges[0];
  182. const auto ref_face = edge_index_to_face_index(ref_edge);
  183. Vector3F ref_normal = N.row(ref_face);
  184. const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
  185. const auto ref_corner_s = (ref_corner_o+1)%3;
  186. const auto ref_corner_d = (ref_corner_o+2)%3;
  187. const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
  188. const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
  189. const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
  190. Vector3E exact_edge = V.row(d) - V.row(s);
  191. exact_edge.array() /= exact_edge.squaredNorm();
  192. Vector3F edge(
  193. CGAL::to_double(exact_edge[0]),
  194. CGAL::to_double(exact_edge[1]),
  195. CGAL::to_double(exact_edge[2]));
  196. edge.normalize();
  197. Eigen::MatrixXd angle_data(edge_valance, 3);
  198. std::vector<bool> cons(edge_valance);
  199. for (size_t fei=0; fei<edge_valance; fei++) {
  200. const auto fe = adj_edges[fei];
  201. const auto f = edge_index_to_face_index(fe);
  202. const auto c = edge_index_to_corner_index(fe);
  203. cons[fei] = (d == F(f, (c+1)%3));
  204. assert( cons[fei] || (d == F(f,(c+2)%3)));
  205. assert(!cons[fei] || (s == F(f,(c+2)%3)));
  206. assert(!cons[fei] || (d == F(f,(c+1)%3)));
  207. Vector3F n = N.row(f);
  208. angle_data(fei, 0) = ref_normal.cross(n).dot(edge);
  209. angle_data(fei, 1) = ref_normal.dot(n);
  210. if (cons[fei]) {
  211. angle_data(fei, 0) *= -1;
  212. angle_data(fei, 1) *= -1;
  213. }
  214. angle_data(fei, 0) *= -1; // Sort clockwise.
  215. angle_data(fei, 2) = (cons[fei]?1.:-1.)*(f+1);
  216. }
  217. Eigen::VectorXi order;
  218. igl::sort_angles(angle_data, order);
  219. auto& ordered_edges = uE2oE[ui];
  220. auto& consistency = uE2C[ui];
  221. ordered_edges.resize(edge_valance);
  222. consistency.resize(edge_valance);
  223. for (size_t fei=0; fei<edge_valance; fei++) {
  224. ordered_edges[fei] = adj_edges[order[fei]];
  225. consistency[fei] = cons[order[fei]];
  226. }
  227. }
  228. }
  229. template<
  230. typename DerivedV,
  231. typename DerivedF,
  232. typename DerivedE,
  233. typename DeriveduE,
  234. typename DerivedEMAP,
  235. typename uE2EType,
  236. typename uE2oEType,
  237. typename uE2CType >
  238. IGL_INLINE void igl::cgal::order_facets_around_edges(
  239. const Eigen::PlainObjectBase<DerivedV>& V,
  240. const Eigen::PlainObjectBase<DerivedF>& F,
  241. const Eigen::PlainObjectBase<DerivedE>& E,
  242. const Eigen::PlainObjectBase<DeriveduE>& uE,
  243. const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
  244. const std::vector<std::vector<uE2EType> >& uE2E,
  245. std::vector<std::vector<uE2oEType> >& uE2oE,
  246. std::vector<std::vector<uE2CType > >& uE2C ) {
  247. typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
  248. const size_t num_faces = F.rows();
  249. const size_t num_undirected_edges = uE.rows();
  250. auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
  251. auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
  252. uE2oE.resize(num_undirected_edges);
  253. uE2C.resize(num_undirected_edges);
  254. for(size_t ui = 0;ui<num_undirected_edges;ui++)
  255. {
  256. const auto& adj_edges = uE2E[ui];
  257. const size_t edge_valance = adj_edges.size();
  258. assert(edge_valance > 0);
  259. const auto ref_edge = adj_edges[0];
  260. const auto ref_face = edge_index_to_face_index(ref_edge);
  261. const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
  262. const auto ref_corner_s = (ref_corner_o+1)%3;
  263. const auto ref_corner_d = (ref_corner_o+2)%3;
  264. const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
  265. const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
  266. const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
  267. std::vector<bool> cons(edge_valance);
  268. std::vector<int> adj_faces(edge_valance);
  269. for (size_t fei=0; fei<edge_valance; fei++) {
  270. const auto fe = adj_edges[fei];
  271. const auto f = edge_index_to_face_index(fe);
  272. const auto c = edge_index_to_corner_index(fe);
  273. cons[fei] = (d == F(f, (c+1)%3));
  274. adj_faces[fei] = (f+1) * (cons[fei] ? 1:-1);
  275. assert( cons[fei] || (d == F(f,(c+2)%3)));
  276. assert(!cons[fei] || (s == F(f,(c+2)%3)));
  277. assert(!cons[fei] || (d == F(f,(c+1)%3)));
  278. }
  279. Eigen::VectorXi order;
  280. order_facets_around_edge(V, F, s, d, adj_faces, order);
  281. assert(order.size() == edge_valance);
  282. auto& ordered_edges = uE2oE[ui];
  283. auto& consistency = uE2C[ui];
  284. ordered_edges.resize(edge_valance);
  285. consistency.resize(edge_valance);
  286. for (size_t fei=0; fei<edge_valance; fei++) {
  287. ordered_edges[fei] = adj_edges[order[fei]];
  288. consistency[fei] = cons[order[fei]];
  289. }
  290. }
  291. }