FillHoneycomb.cpp 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include "../ClipperUtils.hpp"
  2. #include "../ShortestPath.hpp"
  3. #include "../Surface.hpp"
  4. #include "FillHoneycomb.hpp"
  5. namespace Slic3r {
  6. FillHoneycomb::Cache FillHoneycomb::cache{};
  7. void FillHoneycomb::_fill_surface_single(
  8. const FillParams &params,
  9. unsigned int thickness_layers,
  10. const std::pair<float, Point> &direction,
  11. ExPolygon expolygon,
  12. Polylines &polylines_out) const
  13. {
  14. double my_spacing = this->get_spacing();
  15. if(params.max_sparse_infill_spacing > 0)
  16. my_spacing = params.max_sparse_infill_spacing;
  17. // cache hexagons math
  18. CacheID cache_id(params.density, my_spacing);
  19. Cache::iterator it_m = FillHoneycomb::cache.find(cache_id);
  20. if (it_m == FillHoneycomb::cache.end()) {
  21. it_m = FillHoneycomb::cache.insert(it_m, std::pair<CacheID, CacheData>(cache_id, CacheData()));
  22. CacheData &m = it_m->second;
  23. coord_t min_spacing = scale_t(my_spacing);
  24. m.distance = coord_t(double(min_spacing) / params.density);
  25. m.hex_side = coord_t(double(m.distance) / (sqrt(3)/2));
  26. m.hex_width = m.distance * 2; // $m->{hex_width} == $m->{hex_side} * sqrt(3);
  27. coord_t hex_height = m.hex_side * 2;
  28. m.pattern_height = hex_height + m.hex_side;
  29. m.y_short = coord_t(double(m.distance) * sqrt(3)/3);
  30. m.x_offset = min_spacing / 2;
  31. m.y_offset = coord_t(double(m.x_offset) * sqrt(3)/3);
  32. m.hex_center = Point(m.hex_width/2, m.hex_side);
  33. }
  34. CacheData &m = it_m->second;
  35. Polylines all_polylines;
  36. {
  37. // adjust actual bounding box to the nearest multiple of our hex pattern
  38. // and align it so that it matches across layers
  39. BoundingBox bounding_box = expolygon.contour.bounding_box();
  40. {
  41. // rotate bounding box according to infill direction
  42. Polygon bb_polygon = bounding_box.polygon();
  43. bb_polygon.rotate(direction.first, m.hex_center);
  44. bounding_box = bb_polygon.bounding_box();
  45. // extend bounding box so that our pattern will be aligned with other layers
  46. // $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
  47. // The infill is not aligned to the object bounding box, but to a world coordinate system. Supposedly good enough.
  48. bounding_box.merge(align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
  49. }
  50. coord_t x = bounding_box.min(0);
  51. while (x <= bounding_box.max(0)) {
  52. Polyline p;
  53. coord_t ax[2] = { x + m.x_offset, x + m.distance - m.x_offset };
  54. for (size_t i = 0; i < 2; ++ i) {
  55. std::reverse(p.points.begin(), p.points.end()); // turn first half upside down
  56. for (coord_t y = bounding_box.min(1); y <= bounding_box.max(1); y += m.y_short + m.hex_side + m.y_short + m.hex_side) {
  57. p.points.push_back(Point(ax[1], y + m.y_offset));
  58. p.points.push_back(Point(ax[0], y + m.y_short - m.y_offset));
  59. p.points.push_back(Point(ax[0], y + m.y_short + m.hex_side + m.y_offset));
  60. p.points.push_back(Point(ax[1], y + m.y_short + m.hex_side + m.y_short - m.y_offset));
  61. p.points.push_back(Point(ax[1], y + m.y_short + m.hex_side + m.y_short + m.hex_side + m.y_offset));
  62. }
  63. ax[0] = ax[0] + m.distance;
  64. ax[1] = ax[1] + m.distance;
  65. std::swap(ax[0], ax[1]); // draw symmetrical pattern
  66. x += m.distance;
  67. }
  68. p.rotate(-direction.first, m.hex_center);
  69. all_polylines.push_back(p);
  70. }
  71. }
  72. all_polylines = intersection_pl(std::move(all_polylines), expolygon);
  73. if (params.connection == icNotConnected || all_polylines.size() <= 1)
  74. append(polylines_out, chain_polylines(std::move(all_polylines)));
  75. else
  76. connect_infill(std::move(all_polylines), expolygon, polylines_out, scale_t(this->get_spacing()), params);
  77. }
  78. } // namespace Slic3r