order_facets_around_edges.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #include <test_common.h>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <vector>
  5. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  6. #include <igl/copyleft/cgal/order_facets_around_edges.h>
  7. #include <igl/unique_edge_map.h>
  8. #include <igl/readDMAT.h>
  9. #include <igl/per_face_normals.h>
  10. namespace {
  11. typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
  12. template<typename T>
  13. size_t index_of(const std::vector<T>& array, T val) {
  14. auto loc = std::find(array.begin(), array.end(), val);
  15. assert(loc != array.end());
  16. return loc - array.begin();
  17. }
  18. void assert_consistently_oriented(size_t num_faces,
  19. const std::vector<int>& expected_face_order,
  20. const std::vector<int>& e_order) {
  21. const size_t num_items = expected_face_order.size();
  22. REQUIRE (e_order.size() == num_items);
  23. std::vector<int> order(num_items);
  24. std::transform(e_order.begin(), e_order.end(), order.begin(),
  25. [=](int val) { return val % num_faces; });
  26. size_t ref_start = index_of(order, expected_face_order[0]);
  27. for (size_t i=0; i<num_items; i++) {
  28. REQUIRE (order[(ref_start + i) % num_items] == expected_face_order[i]);
  29. }
  30. }
  31. template<typename DerivedV, typename DerivedF>
  32. void assert_order(
  33. const Eigen::PlainObjectBase<DerivedV>& V,
  34. const Eigen::PlainObjectBase<DerivedF>& F,
  35. size_t v0, size_t v1,
  36. std::vector<int> expected_order, const std::string& normal="") {
  37. Eigen::MatrixXi E, uE;
  38. Eigen::VectorXi EMAP;
  39. std::vector<std::vector<int> > uE2E;
  40. igl::unique_edge_map(F, E, uE, EMAP, uE2E);
  41. std::vector<std::vector<int> > uE2oE;
  42. std::vector<std::vector<bool> > uE2C;
  43. if (normal != "") {
  44. Eigen::MatrixXd N;
  45. //igl::per_face_normals_stable(V, F, N);
  46. //igl::per_face_normals(V, F, N);
  47. igl::readDMAT(test_common::data_path(normal), N);
  48. igl::copyleft::cgal::order_facets_around_edges(
  49. V, F, N, uE, uE2E, uE2oE, uE2C);
  50. } else {
  51. igl::copyleft::cgal::order_facets_around_edges(
  52. V, F, uE, uE2E, uE2oE, uE2C);
  53. }
  54. const size_t num_faces = F.rows();
  55. const size_t num_uE = uE.rows();
  56. for (size_t i=0; i<num_uE; i++) {
  57. const auto& order = uE2oE[i];
  58. const auto& cons = uE2C[i];
  59. const auto ref_edge = uE2E[i][0];
  60. const auto ref_face = ref_edge % num_faces;
  61. const auto ref_corner = ref_edge / num_faces;
  62. const Eigen::Vector2i e{
  63. F(ref_face, (ref_corner+1)%3),
  64. F(ref_face, (ref_corner+2)%3) };
  65. if (order.size() <= 1) continue;
  66. if (e[0] != v0 && e[0] != v1) continue;
  67. if (e[1] != v0 && e[1] != v1) continue;
  68. if (e[0] == v1 && e[1] == v0) {
  69. std::reverse(expected_order.begin(), expected_order.end());
  70. }
  71. assert_consistently_oriented(F.rows(), expected_order, order);
  72. }
  73. }
  74. } // anonymous namespace
  75. TEST_CASE("copyleft_cgal_order_facets_around_edges: Simple", "[igl/copyleft/cgal]")
  76. {
  77. Eigen::MatrixXd V(4, 3);
  78. V << 0.0, 0.0, 0.0,
  79. 1.0, 0.0, 0.0,
  80. 0.0, 1.0, 0.0,
  81. 1.0, 1.0, 0.0;
  82. Eigen::MatrixXi F(2, 3);
  83. F << 0, 1, 2,
  84. 2, 1, 3;
  85. assert_order(V, F, 1, 2, {0, 1});
  86. }
  87. TEST_CASE("copyleft_cgal_order_facets_around_edges: TripletFaces", "[igl/copyleft/cgal]")
  88. {
  89. Eigen::MatrixXd V(5, 3);
  90. V << 0.0, 0.0, 0.0,
  91. 1.0, 0.0, 0.0,
  92. 0.0, 1.0, 0.0,
  93. 1.0, 1.0, 0.0,
  94. 0.0, 0.0, 1.0;
  95. Eigen::MatrixXi F(3, 3);
  96. F << 0, 1, 2,
  97. 2, 1, 3,
  98. 1, 2, 4;
  99. assert_order(V, F, 1, 2, {0, 1, 2});
  100. }
  101. TEST_CASE("copyleft_cgal_order_facets_around_edges: DuplicatedFaces", "[igl/copyleft/cgal]")
  102. {
  103. Eigen::MatrixXd V(5, 3);
  104. V << 0.0, 0.0, 0.0,
  105. 1.0, 0.0, 0.0,
  106. 0.0, 1.0, 0.0,
  107. 1.0, 1.0, 0.0,
  108. 0.0, 0.0, 1.0;
  109. Eigen::MatrixXi F(4, 3);
  110. F << 0, 1, 2,
  111. 2, 1, 3,
  112. 1, 2, 4,
  113. 4, 1, 2;
  114. assert_order(V, F, 1, 2, {0, 1, 3, 2});
  115. }
  116. TEST_CASE("copyleft_cgal_order_facets_around_edges: MultipleDuplicatedFaces", "[igl/copyleft/cgal]")
  117. {
  118. Eigen::MatrixXd V(5, 3);
  119. V << 0.0, 0.0, 0.0,
  120. 1.0, 0.0, 0.0,
  121. 0.0, 1.0, 0.0,
  122. 1.0, 1.0, 0.0,
  123. 0.0, 0.0, 1.0;
  124. Eigen::MatrixXi F(6, 3);
  125. F << 0, 1, 2,
  126. 1, 2, 0,
  127. 2, 1, 3,
  128. 1, 3, 2,
  129. 1, 2, 4,
  130. 4, 1, 2;
  131. assert_order(V, F, 1, 2, {1, 0, 2, 3, 5, 4});
  132. }
  133. TEST_CASE("copyleft_cgal_order_facets_around_edges: Debug", "[igl/copyleft/cgal]")
  134. {
  135. Eigen::MatrixXd V(5, 3);
  136. V <<
  137. -44.3205080756887781, 4.22994972382184579e-15, 75,
  138. -27.933756729740665, -48.382685902179837, 75,
  139. -55.8675134594812945, -2.81996648254789745e-15, 75,
  140. -27.933756729740665, -48.382685902179837, 70,
  141. -31.4903810567666049, -42.2224318643354408, 85;
  142. Eigen::MatrixXi F(3, 3);
  143. F << 1, 0, 2,
  144. 2, 3, 1,
  145. 4, 1, 2;
  146. assert_order(V, F, 1, 2, {0, 2, 1});
  147. }
  148. TEST_CASE("copyleft_cgal_order_facets_around_edges: Debug2", "[igl/copyleft/cgal]")
  149. {
  150. Eigen::MatrixXd V(5, 3);
  151. V <<
  152. -22.160254037844382, 38.3826859021798441, 75,
  153. -27.9337567297406331, 48.3826859021798654, 75,
  154. 27.9337567297406544, 48.3826859021798512, 75,
  155. 27.9337567297406544, 48.3826859021798512, 70,
  156. 20.8205080756887924, 48.3826859021798512, 85;
  157. Eigen::MatrixXi F(3, 3);
  158. F << 1, 0, 2,
  159. 3, 1, 2,
  160. 2, 4, 1;
  161. assert_order(V, F, 1, 2, {1, 0, 2});
  162. }
  163. TEST_CASE("copyleft_cgal_order_facets_around_edges: NormalSensitivity", "[igl/copyleft/cgal]")
  164. {
  165. // This example shows that epsilon difference in normal vectors could
  166. // results in very different ordering of facets.
  167. Eigen::MatrixXd V;
  168. igl::readDMAT(test_common::data_path("duplicated_faces_V.dmat"), V);
  169. Eigen::MatrixXi F;
  170. igl::readDMAT(test_common::data_path("duplicated_faces_F.dmat"), F);
  171. assert_order(V, F, 223, 224, {2, 0, 3, 1}, "duplicated_faces_N1.dmat");
  172. assert_order(V, F, 223, 224, {0, 3, 2, 1}, "duplicated_faces_N2.dmat");
  173. }