test_layer_region.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include "libslic3r/ClipperUtils.hpp"
  2. #include "libslic3r/Geometry.hpp"
  3. #include "libslic3r/Point.hpp"
  4. #include "libslic3r/SVG.hpp"
  5. #include <catch2/catch.hpp>
  6. #include <libslic3r/LayerRegion.hpp>
  7. using namespace Slic3r;
  8. using namespace Slic3r::Algorithm;
  9. constexpr bool export_svgs = false;
  10. ExPolygon rectangle(const Point& origin, const int width, const int height) {
  11. return {
  12. origin,
  13. origin + Point{width, 0},
  14. origin + Point{width, height},
  15. origin + Point{0, height},
  16. };
  17. }
  18. struct LayerRegionFixture {
  19. Surfaces surfaces{
  20. Surface{
  21. stBottomBridge,
  22. rectangle({scaled(-1.0), scaled(0.0)}, scaled(1.0), scaled(1.0))
  23. },
  24. Surface{
  25. stBottomBridge,
  26. rectangle({scaled(0.0), scaled(0.0)}, scaled(1.0), scaled(1.0))
  27. },
  28. Surface{
  29. stBottomBridge,
  30. rectangle({scaled(-3.0), scaled(0.0)}, scaled(1.0), scaled(1.0))
  31. }
  32. };
  33. ExPolygons shells{{
  34. rectangle({scaled(-1.0), scaled(1.0)}, scaled(3.0), scaled(1.0))
  35. }};
  36. ExPolygons sparse {{
  37. rectangle({scaled(-2.0), scaled(-1.0)}, scaled(1.0), scaled(3.0))
  38. }};
  39. const float scaled_spacing{scaled(0.3)};
  40. static constexpr const float expansion_step = scaled<float>(0.1);
  41. static constexpr const size_t max_nr_expansion_steps = 5;
  42. const float closing_radius = 0.55f * 0.65f * 1.05f * scaled_spacing;
  43. const int shells_expansion_depth = scaled(0.6);
  44. const RegionExpansionParameters expansion_params_into_solid_infill = RegionExpansionParameters::build(
  45. shells_expansion_depth,
  46. expansion_step,
  47. max_nr_expansion_steps
  48. );
  49. const int sparse_expansion_depth = scaled(0.3);
  50. const RegionExpansionParameters expansion_params_into_sparse_infill = RegionExpansionParameters::build(
  51. sparse_expansion_depth,
  52. expansion_step,
  53. max_nr_expansion_steps
  54. );
  55. std::vector<ExpansionZone> expansion_zones{
  56. ExpansionZone{
  57. std::move(shells),
  58. expansion_params_into_solid_infill,
  59. },
  60. ExpansionZone{
  61. std::move(sparse),
  62. expansion_params_into_sparse_infill,
  63. }
  64. };
  65. };
  66. TEST_CASE_METHOD(LayerRegionFixture, "test the surface expansion", "[LayerRegion]") {
  67. const double custom_angle{1.234f};
  68. const Surfaces result{expand_merge_surfaces(
  69. surfaces, stBottomBridge,
  70. expansion_zones,
  71. closing_radius,
  72. custom_angle
  73. )};
  74. if constexpr (export_svgs) {
  75. SVG svg("general_expansion.svg", BoundingBox{
  76. Point{scaled(-3.0), scaled(-1.0)},
  77. Point{scaled(2.0), scaled(2.0)}
  78. });
  79. svg.draw(surfaces, "blue");
  80. svg.draw(expansion_zones[0].expolygons, "green");
  81. svg.draw(expansion_zones[1].expolygons, "red");
  82. svg.draw_outline(result, "black", "", scale_(0.01));
  83. }
  84. REQUIRE(result.size() == 2);
  85. CHECK(result.at(0).bridge_angle == Approx(custom_angle));
  86. CHECK(result.at(1).bridge_angle == Approx(custom_angle));
  87. CHECK(result.at(0).expolygon.contour.size() == 22);
  88. CHECK(result.at(1).expolygon.contour.size() == 14);
  89. // These lines in the polygons should correspond to the expansion depth.
  90. CHECK(result.at(0).expolygon.contour.lines().at(2).length() == shells_expansion_depth);
  91. CHECK(result.at(1).expolygon.contour.lines().at(7).length() == sparse_expansion_depth);
  92. CHECK(result.at(1).expolygon.contour.lines().at(11).length() == sparse_expansion_depth);
  93. CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[0].expolygons).size() == 0);
  94. CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[1].expolygons).size() == 0);
  95. CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[0].expolygons).size() == 0);
  96. CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[1].expolygons).size() == 0);
  97. }
  98. TEST_CASE_METHOD(LayerRegionFixture, "test the bridge expansion with the bridge angle detection", "[LayerRegion]") {
  99. Surfaces result{expand_bridges_detect_orientations(
  100. surfaces,
  101. expansion_zones,
  102. closing_radius
  103. )};
  104. if constexpr (export_svgs) {
  105. SVG svg("bridge_expansion.svg", BoundingBox{
  106. Point{scaled(-3.0), scaled(-1.0)},
  107. Point{scaled(2.0), scaled(2.0)}
  108. });
  109. svg.draw(surfaces, "blue");
  110. svg.draw(expansion_zones[0].expolygons, "green");
  111. svg.draw(expansion_zones[1].expolygons, "red");
  112. svg.draw_outline(result, "black", "", scale_(0.01));
  113. }
  114. REQUIRE(result.size() == 2);
  115. CHECK(result.at(0).bridge_angle == Approx(1.5707963268));
  116. CHECK(std::fmod(result.at(1).bridge_angle, M_PI) == Approx(0.0));
  117. CHECK(result.at(0).expolygon.contour.size() == 22);
  118. CHECK(result.at(1).expolygon.contour.size() == 14);
  119. // These lines in the polygons should correspond to the expansion depth.
  120. CHECK(result.at(0).expolygon.contour.lines().at(2).length() == shells_expansion_depth);
  121. CHECK(result.at(1).expolygon.contour.lines().at(7).length() == sparse_expansion_depth);
  122. CHECK(result.at(1).expolygon.contour.lines().at(11).length() == sparse_expansion_depth);
  123. CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[0].expolygons).size() == 0);
  124. CHECK(intersection_ex({result.at(0).expolygon}, expansion_zones[1].expolygons).size() == 0);
  125. CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[0].expolygons).size() == 0);
  126. CHECK(intersection_ex({result.at(1).expolygon}, expansion_zones[1].expolygons).size() == 0);
  127. }