diff --git a/lib/Slic3r/Print/GCode.pm b/lib/Slic3r/Print/GCode.pm index e3022fef0..03f9eead0 100644 --- a/lib/Slic3r/Print/GCode.pm +++ b/lib/Slic3r/Print/GCode.pm @@ -35,7 +35,7 @@ sub BUILD { $layer_count = sum(map { $_->total_layer_count } @{$self->objects}); } - # set up our helper object + # set up our helper object: This is a C++ Slic3r::GCode instance. my $gcodegen = Slic3r::GCode->new; $self->_gcodegen($gcodegen); $gcodegen->set_placeholder_parser($self->placeholder_parser); @@ -115,20 +115,21 @@ sub BUILD { if $self->config->pressure_advance > 0; } +# Export a G-code for the complete print. sub export { my ($self) = @_; my $fh = $self->fh; my $gcodegen = $self->_gcodegen; - # write some information + # Write information on the generator. my @lt = localtime; printf $fh "; generated by Slic3r $Slic3r::VERSION on %04d-%02d-%02d at %02d:%02d:%02d\n\n", $lt[5] + 1900, $lt[4]+1, $lt[3], $lt[2], $lt[1], $lt[0]; - + # Write notes (content of the Print Settings tab -> Notes) print $fh "; $_\n" foreach split /\R/, $self->config->notes; print $fh "\n" if $self->config->notes; - + # Write some terse information on the slicing parameters. my $first_object = $self->objects->[0]; my $layer_height = $first_object->config->layer_height; for my $region_id (0..$#{$self->print->regions}) { @@ -155,6 +156,7 @@ sub export { # prepare the helper object for replacing placeholders in custom G-code and output filename $self->placeholder_parser->update_timestamp; + # disable fan print $fh $gcodegen->writer->set_fan(0, 1) if $self->config->cooling && $self->config->disable_fan_first_layers; @@ -340,6 +342,9 @@ sub _print_first_layer_temperature { } } +# Called per object's layer. +# First a $gcode string is collected, +# then filtered and finally written to a file $fh. sub process_layer { my $self = shift; my ($layer, $object_copies) = @_; @@ -484,7 +489,21 @@ sub process_layer { # group extrusions by extruder and then by island my %by_extruder = (); # extruder_id => [ { perimeters => \@perimeters, infill => \@infill } ] - + + my $n_slices = $#{$layer->slices}; + my @layer_surface_bboxes = (); + for my $i (0 .. $n_slices) { + push @layer_surface_bboxes, $layer->slices->[$i]->contour->bounding_box; + } + my $point_inside_surface = sub { + my ($i, $point) = @_; + my $bbox = $layer_surface_bboxes[$i]; + return + $point->x >= $bbox->x_min && $point->x < $bbox->x_max && + $point->y >= $bbox->y_min && $point->y < $bbox->y_max && + $layer->slices->[$i]->contour->contains_point($point); + }; + foreach my $region_id (0..($self->print->region_count-1)) { my $layerm = $layer->regions->[$region_id] or next; my $region = $self->print->get_region($region_id); @@ -499,9 +518,12 @@ sub process_layer { $by_extruder{$extruder_id} //= []; # $perimeter_coll is an ExtrusionPath::Collection object representing a single slice - for my $i (0 .. $#{$layer->slices}) { - if ($i == $#{$layer->slices} - || $layer->slices->[$i]->contour->contains_point($perimeter_coll->first_point)) { + for my $i (0 .. $n_slices) { + if ( + # $perimeter_coll->first_point does not fit inside any slice + $i == $n_slices + # $perimeter_coll->first_point fits inside ith slice + || $point_inside_surface->($i, $perimeter_coll->first_point)) { $by_extruder{$extruder_id}[$i] //= { perimeters => {} }; $by_extruder{$extruder_id}[$i]{perimeters}{$region_id} //= []; push @{ $by_extruder{$extruder_id}[$i]{perimeters}{$region_id} }, @$perimeter_coll; @@ -527,9 +549,9 @@ sub process_layer { $by_extruder{$extruder_id} //= []; # $fill is an ExtrusionPath::Collection object - for my $i (0 .. $#{$layer->slices}) { - if ($i == $#{$layer->slices} - || $layer->slices->[$i]->contour->contains_point($fill->first_point)) { + for my $i (0 .. $n_slices) { + if ($i == $n_slices + || $point_inside_surface->($i, $fill->first_point)) { $by_extruder{$extruder_id}[$i] //= { infill => {} }; $by_extruder{$extruder_id}[$i]{infill}{$region_id} //= []; push @{ $by_extruder{$extruder_id}[$i]{infill}{$region_id} }, $fill; @@ -583,6 +605,7 @@ sub process_layer { print {$self->fh} $self->filter($gcode); } +# Extrude perimeters: Decide where to put seams (hide or align seams). sub _extrude_perimeters { my ($self, $entities_by_region) = @_; @@ -595,6 +618,7 @@ sub _extrude_perimeters { return $gcode; } +# Chain the paths hierarchically by a greedy algorithm to minimize a travel distance. sub _extrude_infill { my ($self, $entities_by_region) = @_; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index e55cefd7b..78e4c0f71 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -393,6 +393,10 @@ sub make_perimeters { for my $i (0 .. ($self->layer_count - 2)) { my $layerm = $self->get_layer($i)->get_region($region_id); my $upper_layerm = $self->get_layer($i+1)->get_region($region_id); + my $upper_layerm_polygons = [ map $_->p, @{$upper_layerm->slices} ]; + # Filter upper layer polygons in intersection_ppl by their bounding boxes? + # my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ]; + my $total_loop_length = sum(map $_->length, @$upper_layerm_polygons) // 0; my $perimeter_spacing = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_spacing; my $ext_perimeter_flow = $layerm->flow(FLOW_ROLE_EXTERNAL_PERIMETER); @@ -415,12 +419,11 @@ sub make_perimeters { # check whether a portion of the upper slices falls inside the critical area my $intersection = intersection_ppl( - [ map $_->p, @{$upper_layerm->slices} ], + $upper_layerm_polygons, $critical_area, ); # only add an additional loop if at least 30% of the slice loop would benefit from it - my $total_loop_length = sum(map $_->length, map $_->p, @{$upper_layerm->slices}) // 0; my $total_intersection_length = sum(map $_->length, @$intersection) // 0; last unless $total_intersection_length > $total_loop_length*0.3;