cut_to_disk.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include <test_common.h>
  2. #include <igl/cut_mesh.h>
  3. #include <igl/cut_to_disk.h>
  4. #include <igl/edges.h>
  5. #include <array>
  6. #include <iostream>
  7. #include <vector>
  8. #include <set>
  9. namespace cut_to_disk_helper {
  10. template<typename DerivedV, typename DerivedF>
  11. void assert_is_disk(
  12. const Eigen::PlainObjectBase<DerivedV>& V,
  13. const Eigen::PlainObjectBase<DerivedF>& F,
  14. const std::vector<std::vector<int>>& cuts) {
  15. using namespace igl;
  16. std::set<std::array<int, 2>> cut_edges;
  17. for (const auto& cut : cuts) {
  18. const size_t cut_len = cut.size();
  19. for (size_t i=0; i<cut_len-1; i++) {
  20. std::array<int, 2> e{cut[i], cut[i+1]};
  21. if (e[0] > e[1]) {
  22. std::swap(e[0], e[1]);
  23. }
  24. cut_edges.insert(e);
  25. }
  26. }
  27. const size_t num_faces = F.rows();
  28. Eigen::MatrixXi cut_mask(num_faces, 3);
  29. cut_mask.setZero();
  30. for (size_t i=0; i<num_faces; i++) {
  31. std::array<int, 2> e0{F(i, 0), F(i, 1)};
  32. std::array<int, 2> e1{F(i, 1), F(i, 2)};
  33. std::array<int, 2> e2{F(i, 2), F(i, 0)};
  34. if (e0[0] > e0[1]) std::swap(e0[0], e0[1]);
  35. if (e1[0] > e1[1]) std::swap(e1[0], e1[1]);
  36. if (e2[0] > e2[1]) std::swap(e2[0], e2[1]);
  37. if (cut_edges.find(e0) != cut_edges.end()) {
  38. cut_mask(i, 0) = 1;
  39. }
  40. if (cut_edges.find(e1) != cut_edges.end()) {
  41. cut_mask(i, 1) = 1;
  42. }
  43. if (cut_edges.find(e2) != cut_edges.end()) {
  44. cut_mask(i, 2) = 1;
  45. }
  46. }
  47. Eigen::MatrixXd V2;
  48. Eigen::MatrixXi F2;
  49. igl::cut_mesh(V, F, cut_mask, V2, F2);
  50. Eigen::MatrixXi E2;
  51. edges(F2, E2);
  52. const auto euler = V2.rows() - E2.rows() + F2.rows();
  53. CHECK ((1 == euler || 2 == euler));
  54. }
  55. }
  56. TEST_CASE("cut_to_disk: simple_tet", "[igl]")
  57. {
  58. using namespace igl;
  59. Eigen::MatrixXi F(4, 3);
  60. F << 0, 2, 1,
  61. 0, 3, 2,
  62. 1, 2, 3,
  63. 0, 1, 3;
  64. std::vector<std::vector<int>> cuts;
  65. cut_to_disk(F, cuts);
  66. REQUIRE (cuts.size() == 0);
  67. }
  68. TEST_CASE("cut_to_disk: two_disconnected_tet", "[igl]")
  69. {
  70. using namespace igl;
  71. Eigen::MatrixXi F(8, 3);
  72. F << 0, 2, 1,
  73. 0, 3, 2,
  74. 1, 2, 3,
  75. 0, 1, 3,
  76. 4, 6, 5,
  77. 4, 7, 6,
  78. 5, 6, 7,
  79. 4, 5, 7;
  80. std::vector<std::vector<int>> cuts;
  81. cut_to_disk(F, cuts);
  82. REQUIRE (cuts.size() == 0);
  83. }
  84. TEST_CASE("cut_to_disk: simple_square", "[igl]")
  85. {
  86. using namespace igl;
  87. Eigen::MatrixXi F(2, 3);
  88. F << 0, 1, 2,
  89. 2, 1, 3;
  90. std::vector<std::vector<int>> cuts;
  91. cut_to_disk(F, cuts);
  92. REQUIRE (cuts.size() == 1);
  93. REQUIRE (cuts[0].size() == 5);
  94. REQUIRE (cuts[0][4] == cuts[0][0]);
  95. }
  96. TEST_CASE("cut_to_disk: torus", "[igl]")
  97. {
  98. using namespace igl;
  99. Eigen::MatrixXd V;
  100. Eigen::MatrixXi F;
  101. test_common::load_mesh("TinyTorus.obj", V, F);
  102. std::vector<std::vector<int>> cuts;
  103. cut_to_disk(F, cuts);
  104. REQUIRE (cuts.size() == 2);
  105. cut_to_disk_helper::assert_is_disk(V, F, cuts);
  106. }
  107. TEST_CASE("cut_to_disk: cube", "[igl]")
  108. {
  109. using namespace igl;
  110. Eigen::MatrixXd V;
  111. Eigen::MatrixXi F;
  112. test_common::load_mesh("cube.obj", V, F);
  113. std::vector<std::vector<int>> cuts;
  114. cut_to_disk(F, cuts);
  115. REQUIRE (cuts.size() == 0);
  116. cut_to_disk_helper::assert_is_disk(V, F, cuts);
  117. }