Concentric.pm 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package Slic3r::Fill::Concentric;
  2. use Moo;
  3. extends 'Slic3r::Fill::Base';
  4. use Slic3r::Geometry qw(scale unscale X);
  5. use Slic3r::Geometry::Clipper qw(offset offset2 union_pt_chained);
  6. sub fill_surface {
  7. my $self = shift;
  8. my ($surface, %params) = @_;
  9. # no rotation is supported for this infill pattern
  10. my $expolygon = $surface->expolygon;
  11. my $bounding_box = $expolygon->bounding_box;
  12. my $flow = $params{flow};
  13. my $min_spacing = $flow->scaled_spacing;
  14. my $distance = $min_spacing / $params{density};
  15. my $flow_spacing = $flow->spacing;
  16. if ($params{density} == 1 && !$params{dont_adjust}) {
  17. $distance = $self->adjust_solid_spacing(
  18. width => $bounding_box->size->[X],
  19. distance => $distance,
  20. );
  21. $flow = Slic3r::Flow->new_from_spacing(
  22. spacing => unscale($distance),
  23. nozzle_diameter => $flow->nozzle_diameter,
  24. layer_height => $surface->thickness,
  25. bridge => $flow->bridge,
  26. );
  27. }
  28. # compensate the overlap which is good for rectilinear but harmful for concentric
  29. # where the perimeter/infill spacing should be equal to any other loop spacing
  30. my @loops = my @last = @{offset(\@$expolygon, -&Slic3r::INFILL_OVERLAP_OVER_SPACING * $min_spacing / 2)};
  31. while (@last) {
  32. push @loops, @last = @{offset2(\@last, -1.5*$distance, +0.5*$distance)};
  33. }
  34. # generate paths from the outermost to the innermost, to avoid
  35. # adhesion problems of the first central tiny loops
  36. @loops = map Slic3r::Polygon->new(@$_),
  37. reverse @{union_pt_chained(\@loops)};
  38. # order paths using a nearest neighbor search
  39. my @paths = ();
  40. my $last_pos = Slic3r::Point->new(0,0);
  41. foreach my $loop (@loops) {
  42. push @paths, $loop->split_at_index($last_pos->nearest_point_index(\@$loop));
  43. $last_pos = $paths[-1]->last_point;
  44. }
  45. # clip the paths to prevent the extruder from getting exactly on the first point of the loop
  46. my $clip_length = scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
  47. $_->clip_end($clip_length) for @paths;
  48. @paths = grep $_->is_valid, @paths; # remove empty paths (too short, thus eaten by clipping)
  49. # TODO: return ExtrusionLoop objects to get better chained paths
  50. return { flow => $flow, no_sort => 1 }, @paths;
  51. }
  52. 1;