test_surface_mesh.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <catch2/catch.hpp>
  2. #include <test_utils.hpp>
  3. #include <libslic3r/SurfaceMesh.hpp>
  4. using namespace Slic3r;
  5. // Generate a broken cube mesh. Face 8 is inverted, face 11 is missing.
  6. indexed_triangle_set its_make_cube_broken(double xd, double yd, double zd)
  7. {
  8. auto x = float(xd), y = float(yd), z = float(zd);
  9. return {
  10. { {0, 1, 2}, {0, 2, 3}, {4, 5, 6}, {4, 6, 7},
  11. {0, 4, 7}, {0, 7, 1}, {1, 7, 6}, {1, 6, 2},
  12. {2, 5, 6}, {2, 5, 3}, {4, 0, 3} /*missing face*/ },
  13. { {x, y, 0}, {x, 0, 0}, {0, 0, 0}, {0, y, 0},
  14. {x, y, z}, {0, y, z}, {0, 0, z}, {x, 0, z} }
  15. };
  16. }
  17. TEST_CASE("SurfaceMesh on a cube", "[SurfaceMesh]") {
  18. indexed_triangle_set cube = its_make_cube(1., 1., 1.);
  19. SurfaceMesh sm(cube);
  20. const Halfedge_index hi_first = sm.halfedge(Face_index(0));
  21. Halfedge_index hi = hi_first;
  22. REQUIRE(! hi_first.is_invalid());
  23. SECTION("next / prev halfedge") {
  24. hi = sm.next(hi);
  25. REQUIRE(hi != hi_first);
  26. hi = sm.next(hi);
  27. hi = sm.next(hi);
  28. REQUIRE(hi == hi_first);
  29. hi = sm.prev(hi);
  30. REQUIRE(hi != hi_first);
  31. hi = sm.prev(hi);
  32. hi = sm.prev(hi);
  33. REQUIRE(hi == hi_first);
  34. }
  35. SECTION("next_around_target") {
  36. // Check that we get to the same halfedge after applying next_around_target
  37. // four times.
  38. const Vertex_index target_vert = sm.target(hi_first);
  39. for (int i=0; i<4;++i) {
  40. hi = sm.next_around_target(hi);
  41. REQUIRE((hi == hi_first) == (i == 3));
  42. REQUIRE(sm.is_same_vertex(sm.target(hi), target_vert));
  43. REQUIRE(! sm.is_border(hi));
  44. }
  45. }
  46. SECTION("iterate around target and source") {
  47. hi = sm.next_around_target(hi);
  48. hi = sm.prev_around_target(hi);
  49. hi = sm.prev_around_source(hi);
  50. hi = sm.next_around_source(hi);
  51. REQUIRE(hi == hi_first);
  52. }
  53. SECTION("opposite") {
  54. const Vertex_index target = sm.target(hi);
  55. const Vertex_index source = sm.source(hi);
  56. hi = sm.opposite(hi);
  57. REQUIRE(sm.is_same_vertex(target, sm.source(hi)));
  58. REQUIRE(sm.is_same_vertex(source, sm.target(hi)));
  59. hi = sm.opposite(hi);
  60. REQUIRE(hi == hi_first);
  61. }
  62. SECTION("halfedges walk") {
  63. for (int i=0; i<4; ++i) {
  64. hi = sm.next(hi);
  65. hi = sm.opposite(hi);
  66. }
  67. REQUIRE(hi == hi_first);
  68. }
  69. SECTION("point accessor") {
  70. Halfedge_index hi = sm.halfedge(Face_index(0));
  71. hi = sm.opposite(hi);
  72. hi = sm.prev(hi);
  73. hi = sm.opposite(hi);
  74. REQUIRE(hi.face() == Face_index(6));
  75. REQUIRE(sm.point(sm.target(hi)).isApprox(cube.vertices[7]));
  76. }
  77. }
  78. TEST_CASE("SurfaceMesh on a broken cube", "[SurfaceMesh]") {
  79. indexed_triangle_set cube = its_make_cube_broken(1., 1., 1.);
  80. SurfaceMesh sm(cube);
  81. SECTION("Check inverted face") {
  82. Halfedge_index hi = sm.halfedge(Face_index(8));
  83. for (int i=0; i<3; ++i) {
  84. REQUIRE(! hi.is_invalid());
  85. REQUIRE(sm.is_border(hi));
  86. }
  87. REQUIRE(hi == sm.halfedge(Face_index(8)));
  88. hi = sm.opposite(hi);
  89. REQUIRE(hi.is_invalid());
  90. }
  91. SECTION("missing face") {
  92. Halfedge_index hi = sm.halfedge(Face_index(0));
  93. for (int i=0; i<3; ++i)
  94. hi = sm.next_around_source(hi);
  95. hi = sm.next(hi);
  96. REQUIRE(sm.is_border(hi));
  97. REQUIRE(! hi.is_invalid());
  98. hi = sm.opposite(hi);
  99. REQUIRE(hi.is_invalid());
  100. }
  101. }