Fill.pm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package Slic3r::Fill;
  2. use Moo;
  3. use Slic3r::Fill::ArchimedeanChords;
  4. use Slic3r::Fill::Base;
  5. use Slic3r::Fill::Concentric;
  6. use Slic3r::Fill::Flowsnake;
  7. use Slic3r::Fill::HilbertCurve;
  8. use Slic3r::Fill::Honeycomb;
  9. use Slic3r::Fill::Line;
  10. use Slic3r::Fill::OctagramSpiral;
  11. use Slic3r::Fill::PlanePath;
  12. use Slic3r::Fill::Rectilinear;
  13. use Slic3r::ExtrusionPath ':roles';
  14. use Slic3r::Geometry qw(X Y scale shortest_path);
  15. use Slic3r::Geometry::Clipper qw(union_ex diff_ex);
  16. use Slic3r::Surface ':types';
  17. has 'print' => (is => 'ro', required => 1);
  18. has 'max_print_dimension' => (is => 'rw');
  19. has 'fillers' => (is => 'rw', default => sub { {} });
  20. our %FillTypes = (
  21. archimedeanchords => 'Slic3r::Fill::ArchimedeanChords',
  22. rectilinear => 'Slic3r::Fill::Rectilinear',
  23. flowsnake => 'Slic3r::Fill::Flowsnake',
  24. octagramspiral => 'Slic3r::Fill::OctagramSpiral',
  25. hilbertcurve => 'Slic3r::Fill::HilbertCurve',
  26. line => 'Slic3r::Fill::Line',
  27. concentric => 'Slic3r::Fill::Concentric',
  28. honeycomb => 'Slic3r::Fill::Honeycomb',
  29. );
  30. sub BUILD {
  31. my $self = shift;
  32. my $print_size = $self->print->size;
  33. my $max_print_dimension = ($print_size->[X] > $print_size->[Y] ? $print_size->[X] : $print_size->[Y]) * sqrt(2);
  34. $self->max_print_dimension($max_print_dimension);
  35. $self->filler($_) for ('rectilinear', $Slic3r::Config->fill_pattern, $Slic3r::Config->solid_fill_pattern);
  36. }
  37. sub filler {
  38. my $self = shift;
  39. my ($filler) = @_;
  40. if (!$self->fillers->{$filler}) {
  41. $self->fillers->{$filler} = $FillTypes{$filler}->new(print => $self->print);
  42. $self->fillers->{$filler}->max_print_dimension($self->max_print_dimension);
  43. }
  44. return $self->fillers->{$filler};
  45. }
  46. sub make_fill {
  47. my $self = shift;
  48. my ($layer) = @_;
  49. $_->layer($layer) for values %{$self->fillers};
  50. Slic3r::debugf "Filling layer %d:\n", $layer->id;
  51. # merge overlapping surfaces
  52. my @surfaces = ();
  53. {
  54. my @surfaces_with_bridge_angle = grep defined $_->bridge_angle, @{$layer->fill_surfaces};
  55. # give priority to bridges
  56. my @groups = Slic3r::Surface->group({merge_solid => 1}, @{$layer->fill_surfaces});
  57. @groups = sort { defined $a->[0]->bridge_angle ? -1 : 0 } @groups;
  58. foreach my $group (@groups) {
  59. my $union = union_ex([ map $_->p, @$group ], undef, 1);
  60. # subtract surfaces having a defined bridge_angle from any other
  61. if (@surfaces_with_bridge_angle && !defined $group->[0]->bridge_angle) {
  62. $union = diff_ex(
  63. [ map @$_, @$union ],
  64. [ map $_->p, @surfaces_with_bridge_angle ],
  65. 1,
  66. );
  67. }
  68. # subtract any other surface already processed
  69. $union = diff_ex(
  70. [ map @$_, @$union ],
  71. [ map $_->p, @surfaces ],
  72. 1,
  73. );
  74. push @surfaces, map Slic3r::Surface->new(
  75. expolygon => $_,
  76. surface_type => $group->[0]->surface_type,
  77. bridge_angle => $group->[0]->bridge_angle,
  78. depth_layers => $group->[0]->depth_layers,
  79. ), @$union;
  80. }
  81. }
  82. # add spacing between adjacent surfaces
  83. {
  84. my $distance = $layer->infill_flow->scaled_spacing / 2;
  85. my @offsets = ();
  86. foreach my $surface (@surfaces) {
  87. my $expolygon = $surface->expolygon;
  88. my $diff = diff_ex(
  89. [ $expolygon->offset($distance) ],
  90. $expolygon,
  91. 1,
  92. );
  93. push @offsets, map @$_, @$diff;
  94. }
  95. my @new_surfaces = ();
  96. foreach my $surface (@surfaces) {
  97. my $diff = diff_ex(
  98. $surface->expolygon,
  99. [ @offsets ],
  100. );
  101. push @new_surfaces, map Slic3r::Surface->new(
  102. expolygon => $_,
  103. surface_type => $surface->surface_type,
  104. bridge_angle => $surface->bridge_angle,
  105. depth_layers => $surface->depth_layers,
  106. ), @$diff;
  107. }
  108. @surfaces = @new_surfaces;
  109. }
  110. my @fills = ();
  111. my @fills_ordering_points = ();
  112. SURFACE: foreach my $surface (@surfaces) {
  113. my $filler = $Slic3r::Config->fill_pattern;
  114. my $density = $Slic3r::Config->fill_density;
  115. my $flow_spacing = $layer->infill_flow->spacing;
  116. my $is_bridge = $layer->id > 0 && $surface->surface_type == S_TYPE_BOTTOM;
  117. my $is_solid = (grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID) ? 1 : 0;
  118. # force 100% density and rectilinear fill for external surfaces
  119. if ($surface->surface_type != S_TYPE_INTERNAL) {
  120. $density = 1;
  121. $filler = $Slic3r::Config->solid_fill_pattern;
  122. if ($is_bridge) {
  123. $filler = 'rectilinear';
  124. $flow_spacing = sqrt($Slic3r::Config->bridge_flow_ratio * ($layer->infill_flow->nozzle_diameter**2));
  125. } elsif ($surface->surface_type == S_TYPE_INTERNALSOLID) {
  126. $filler = 'rectilinear';
  127. }
  128. } else {
  129. next SURFACE unless $density > 0;
  130. }
  131. my @paths = $self->fillers->{$filler}->fill_surface(
  132. $surface,
  133. density => $density,
  134. flow_spacing => $flow_spacing,
  135. );
  136. my $params = shift @paths;
  137. # save into layer
  138. next unless @paths;
  139. push @fills, Slic3r::ExtrusionPath::Collection->new(
  140. paths => [
  141. map Slic3r::ExtrusionPath->pack(
  142. polyline => Slic3r::Polyline->new(@$_),
  143. role => ($is_bridge
  144. ? EXTR_ROLE_BRIDGE
  145. : $is_solid
  146. ? ($surface->surface_type == S_TYPE_TOP ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
  147. : EXTR_ROLE_FILL),
  148. height => $surface->depth_layers * $Slic3r::Config->layer_height,
  149. flow_spacing => $params->{flow_spacing} || (warn "Warning: no flow_spacing was returned by the infill engine, please report this to the developer\n"),
  150. ), @paths,
  151. ],
  152. );
  153. push @fills_ordering_points, $paths[0][0];
  154. }
  155. # add thin fill regions
  156. push @fills, @{$layer->thin_fills};
  157. push @fills_ordering_points, map $_->unpack->points->[0], @{$layer->thin_fills};
  158. # organize infill paths using a shortest path search
  159. @fills = @{shortest_path([
  160. map [ $fills_ordering_points[$_], $fills[$_] ], 0..$#fills,
  161. ])};
  162. return @fills;
  163. }
  164. 1;