Layer.pm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package Slic3r::Layer;
  2. use strict;
  3. use warnings;
  4. use List::Util qw(first);
  5. use Slic3r::Geometry::Clipper qw(union_ex intersection_ex);
  6. # the following two were previously generated by Moo
  7. sub print {
  8. my $self = shift;
  9. return $self->object->print;
  10. }
  11. sub config {
  12. my $self = shift;
  13. return $self->object->config;
  14. }
  15. # the purpose of this method is to be overridden for ::Support layers
  16. sub islands {
  17. my $self = shift;
  18. return $self->slices;
  19. }
  20. sub region {
  21. my $self = shift;
  22. my ($region_id) = @_;
  23. while ($self->region_count <= $region_id) {
  24. $self->add_region($self->object->print->get_region($self->region_count));
  25. }
  26. return $self->get_region($region_id);
  27. }
  28. sub regions {
  29. my ($self) = @_;
  30. return [ map $self->get_region($_), 0..($self->region_count-1) ];
  31. }
  32. sub merge_slices {
  33. my ($self) = @_;
  34. $_->merge_slices for @{$self->regions};
  35. }
  36. sub make_perimeters {
  37. my $self = shift;
  38. Slic3r::debugf "Making perimeters for layer %d\n", $self->id;
  39. # keep track of regions whose perimeters we have already generated
  40. my %done = (); # region_id => 1
  41. for my $region_id (0..$#{$self->regions}) {
  42. next if $done{$region_id};
  43. my $layerm = $self->regions->[$region_id];
  44. $done{$region_id} = 1;
  45. # find compatible regions
  46. my @layerms = ($layerm);
  47. for my $i (($region_id+1)..$#{$self->regions}) {
  48. my $config = $self->regions->[$i]->config;
  49. my $layerm_config = $layerm->config;
  50. if ($config->perimeter_extruder == $layerm_config->perimeter_extruder
  51. && $config->perimeters == $layerm_config->perimeters
  52. && $config->perimeter_speed == $layerm_config->perimeter_speed
  53. && $config->gap_fill_speed == $layerm_config->gap_fill_speed
  54. && $config->overhangs == $layerm_config->overhangs
  55. && $config->perimeter_extrusion_width == $layerm_config->perimeter_extrusion_width
  56. && $config->thin_walls == $layerm_config->thin_walls
  57. && $config->external_perimeters_first == $layerm_config->external_perimeters_first) {
  58. push @layerms, $self->regions->[$i];
  59. $done{$i} = 1;
  60. }
  61. }
  62. if (@layerms == 1) { # optimization
  63. $layerm->fill_surfaces->clear;
  64. $layerm->make_perimeters($layerm->slices, $layerm->fill_surfaces);
  65. } else {
  66. # group slices (surfaces) according to number of extra perimeters
  67. my %slices = (); # extra_perimeters => [ surface, surface... ]
  68. foreach my $surface (map @{$_->slices}, @layerms) {
  69. my $extra = $surface->extra_perimeters;
  70. $slices{$extra} ||= [];
  71. push @{$slices{$extra}}, $surface;
  72. }
  73. # merge the surfaces assigned to each group
  74. my $new_slices = Slic3r::Surface::Collection->new;
  75. foreach my $surfaces (values %slices) {
  76. $new_slices->append(Slic3r::Surface->new(
  77. surface_type => $surfaces->[0]->surface_type,
  78. extra_perimeters => $surfaces->[0]->extra_perimeters,
  79. expolygon => $_,
  80. )) for @{union_ex([ map $_->p, @$surfaces ], 1)};
  81. }
  82. # make perimeters
  83. my $fill_surfaces = Slic3r::Surface::Collection->new;
  84. $layerm->make_perimeters($new_slices, $fill_surfaces);
  85. # assign fill_surfaces to each layer
  86. if ($fill_surfaces->count > 0) {
  87. foreach my $lm (@layerms) {
  88. my $expolygons = intersection_ex(
  89. [ map $_->p, @$fill_surfaces ],
  90. [ map $_->p, @{$lm->slices} ],
  91. );
  92. $lm->fill_surfaces->clear;
  93. $lm->fill_surfaces->append(Slic3r::Surface->new(
  94. surface_type => $fill_surfaces->[0]->surface_type,
  95. extra_perimeters => $fill_surfaces->[0]->extra_perimeters,
  96. expolygon => $_,
  97. )) for @$expolygons;
  98. }
  99. }
  100. }
  101. }
  102. }
  103. package Slic3r::Layer::Support;
  104. our @ISA = qw(Slic3r::Layer);
  105. sub islands {
  106. my $self = shift;
  107. return [ @{$self->slices}, @{$self->support_islands} ];
  108. }
  109. 1;