Layer.pm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package Slic3r::Layer;
  2. use Moo;
  3. use List::Util qw(first);
  4. use Slic3r::Geometry qw(scale);
  5. use Slic3r::Geometry::Clipper qw(union_ex);
  6. has 'id' => (is => 'rw', required => 1, trigger => 1); # sequential number of layer, 0-based
  7. has 'object' => (is => 'ro', weak_ref => 1, required => 1);
  8. has 'regions' => (is => 'ro', default => sub { [] });
  9. has 'slicing_errors' => (is => 'rw');
  10. has 'slice_z' => (is => 'lazy');
  11. has 'print_z' => (is => 'lazy');
  12. has 'height' => (is => 'lazy');
  13. has 'flow' => (is => 'lazy');
  14. # collection of expolygons generated by slicing the original geometry;
  15. # also known as 'islands' (all regions are merged here)
  16. has 'slices' => (is => 'rw');
  17. # ordered collection of extrusion paths to fill surfaces for support material
  18. has 'support_islands' => (is => 'rw');
  19. has 'support_fills' => (is => 'rw');
  20. has 'support_contact_fills' => (is => 'rw');
  21. sub _trigger_id {
  22. my $self = shift;
  23. $_->_trigger_layer for @{$self->regions || []};
  24. }
  25. # Z used for slicing in scaled coordinates
  26. sub _build_slice_z {
  27. my $self = shift;
  28. if ($Slic3r::Config->raft_layers == 0) {
  29. if ($self->id == 0) {
  30. return scale $Slic3r::Config->get_value('first_layer_height') / 2;
  31. }
  32. return scale($Slic3r::Config->get_value('first_layer_height') + ($self->id-1 + 0.5) * $Slic3r::Config->layer_height);
  33. } else {
  34. return -1 if $self->id < $Slic3r::Config->raft_layers;
  35. my $object_layer_id = $self->id - $Slic3r::Config->raft_layers;
  36. return scale ($object_layer_id + 0.5) * $Slic3r::Config->layer_height;
  37. }
  38. }
  39. # Z used for printing in scaled coordinates
  40. sub _build_print_z {
  41. my $self = shift;
  42. return ($Slic3r::Config->get_value('first_layer_height') + ($self->id * $Slic3r::Config->layer_height)) / &Slic3r::SCALING_FACTOR;
  43. }
  44. # layer height in unscaled coordinates
  45. sub _build_height {
  46. my $self = shift;
  47. return $self->id == 0 ? $Slic3r::Config->get_value('first_layer_height') : $Slic3r::Config->layer_height;
  48. }
  49. sub _build_flow { $Slic3r::flow }
  50. # layer height of contact paths in unscaled coordinates
  51. sub support_material_contact_height {
  52. my $self = shift;
  53. return $self->height if $self->id == 0;
  54. # this is not very correct because:
  55. # - we should sum our height with the actual upper layers height (which might be different)
  56. # - we should use the actual flow of the upper layer bridges, not the default one
  57. # ...but we're close enough for now
  58. return 2*$self->height - $self->flow->nozzle_diameter;
  59. }
  60. # Z used for printing support material contact in scaled coordinates
  61. sub support_material_contact_z {
  62. my $self = shift;
  63. return $self->print_z - ($self->height - $self->support_material_contact_height) / &Slic3r::SCALING_FACTOR;
  64. }
  65. sub region {
  66. my $self = shift;
  67. my ($region_id) = @_;
  68. for (my $i = @{$self->regions}; $i <= $region_id; $i++) {
  69. $self->regions->[$i] //= Slic3r::Layer::Region->new(
  70. layer => $self,
  71. region => $self->object->print->regions->[$i],
  72. );
  73. }
  74. return $self->regions->[$region_id];
  75. }
  76. # merge all regions' slices to get islands
  77. sub make_slices {
  78. my $self = shift;
  79. # optimization for single-region layers
  80. my @regions_with_slices = grep { @{$_->slices} } @{$self->regions};
  81. if (@regions_with_slices == 1) {
  82. $self->slices([ map $_->expolygon, @{$regions_with_slices[0]->slices} ]);
  83. return;
  84. }
  85. $self->slices(union_ex([ map $_->p, map @{$_->slices}, @{$self->regions} ]));
  86. }
  87. sub make_perimeters {
  88. my $self = shift;
  89. Slic3r::debugf "Making perimeters for layer %d\n", $self->id;
  90. $_->make_perimeters for @{$self->regions};
  91. }
  92. sub support_islands_enclose_line {
  93. my $self = shift;
  94. my ($line) = @_;
  95. return (first { $_->encloses_line($line) } @{$self->support_islands}) ? 1 : 0;
  96. }
  97. 1;