mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-06-30 16:55:08 +08:00
Fix of git #3293: More efficient GCode export
This fixes two problems of repeatedly copying data from the C++ layer to perl, by factoring the copying out of an inner loop.
This commit is contained in:
parent
ab9e3b718c
commit
bb9c3dd9ce
@ -35,7 +35,7 @@ sub BUILD {
|
|||||||
$layer_count = sum(map { $_->total_layer_count } @{$self->objects});
|
$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;
|
my $gcodegen = Slic3r::GCode->new;
|
||||||
$self->_gcodegen($gcodegen);
|
$self->_gcodegen($gcodegen);
|
||||||
$gcodegen->set_placeholder_parser($self->placeholder_parser);
|
$gcodegen->set_placeholder_parser($self->placeholder_parser);
|
||||||
@ -115,20 +115,21 @@ sub BUILD {
|
|||||||
if $self->config->pressure_advance > 0;
|
if $self->config->pressure_advance > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Export a G-code for the complete print.
|
||||||
sub export {
|
sub export {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
my $fh = $self->fh;
|
my $fh = $self->fh;
|
||||||
my $gcodegen = $self->_gcodegen;
|
my $gcodegen = $self->_gcodegen;
|
||||||
|
|
||||||
# write some information
|
# Write information on the generator.
|
||||||
my @lt = localtime;
|
my @lt = localtime;
|
||||||
printf $fh "; generated by Slic3r $Slic3r::VERSION on %04d-%02d-%02d at %02d:%02d:%02d\n\n",
|
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];
|
$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" foreach split /\R/, $self->config->notes;
|
||||||
print $fh "\n" if $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 $first_object = $self->objects->[0];
|
||||||
my $layer_height = $first_object->config->layer_height;
|
my $layer_height = $first_object->config->layer_height;
|
||||||
for my $region_id (0..$#{$self->print->regions}) {
|
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
|
# prepare the helper object for replacing placeholders in custom G-code and output filename
|
||||||
$self->placeholder_parser->update_timestamp;
|
$self->placeholder_parser->update_timestamp;
|
||||||
|
|
||||||
|
# disable fan
|
||||||
print $fh $gcodegen->writer->set_fan(0, 1)
|
print $fh $gcodegen->writer->set_fan(0, 1)
|
||||||
if $self->config->cooling && $self->config->disable_fan_first_layers;
|
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 {
|
sub process_layer {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($layer, $object_copies) = @_;
|
my ($layer, $object_copies) = @_;
|
||||||
@ -485,6 +490,20 @@ sub process_layer {
|
|||||||
# group extrusions by extruder and then by island
|
# group extrusions by extruder and then by island
|
||||||
my %by_extruder = (); # extruder_id => [ { perimeters => \@perimeters, infill => \@infill } ]
|
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)) {
|
foreach my $region_id (0..($self->print->region_count-1)) {
|
||||||
my $layerm = $layer->regions->[$region_id] or next;
|
my $layerm = $layer->regions->[$region_id] or next;
|
||||||
my $region = $self->print->get_region($region_id);
|
my $region = $self->print->get_region($region_id);
|
||||||
@ -499,9 +518,12 @@ sub process_layer {
|
|||||||
$by_extruder{$extruder_id} //= [];
|
$by_extruder{$extruder_id} //= [];
|
||||||
|
|
||||||
# $perimeter_coll is an ExtrusionPath::Collection object representing a single slice
|
# $perimeter_coll is an ExtrusionPath::Collection object representing a single slice
|
||||||
for my $i (0 .. $#{$layer->slices}) {
|
for my $i (0 .. $n_slices) {
|
||||||
if ($i == $#{$layer->slices}
|
if (
|
||||||
|| $layer->slices->[$i]->contour->contains_point($perimeter_coll->first_point)) {
|
# $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 => {} };
|
||||||
$by_extruder{$extruder_id}[$i]{perimeters}{$region_id} //= [];
|
$by_extruder{$extruder_id}[$i]{perimeters}{$region_id} //= [];
|
||||||
push @{ $by_extruder{$extruder_id}[$i]{perimeters}{$region_id} }, @$perimeter_coll;
|
push @{ $by_extruder{$extruder_id}[$i]{perimeters}{$region_id} }, @$perimeter_coll;
|
||||||
@ -527,9 +549,9 @@ sub process_layer {
|
|||||||
$by_extruder{$extruder_id} //= [];
|
$by_extruder{$extruder_id} //= [];
|
||||||
|
|
||||||
# $fill is an ExtrusionPath::Collection object
|
# $fill is an ExtrusionPath::Collection object
|
||||||
for my $i (0 .. $#{$layer->slices}) {
|
for my $i (0 .. $n_slices) {
|
||||||
if ($i == $#{$layer->slices}
|
if ($i == $n_slices
|
||||||
|| $layer->slices->[$i]->contour->contains_point($fill->first_point)) {
|
|| $point_inside_surface->($i, $fill->first_point)) {
|
||||||
$by_extruder{$extruder_id}[$i] //= { infill => {} };
|
$by_extruder{$extruder_id}[$i] //= { infill => {} };
|
||||||
$by_extruder{$extruder_id}[$i]{infill}{$region_id} //= [];
|
$by_extruder{$extruder_id}[$i]{infill}{$region_id} //= [];
|
||||||
push @{ $by_extruder{$extruder_id}[$i]{infill}{$region_id} }, $fill;
|
push @{ $by_extruder{$extruder_id}[$i]{infill}{$region_id} }, $fill;
|
||||||
@ -583,6 +605,7 @@ sub process_layer {
|
|||||||
print {$self->fh} $self->filter($gcode);
|
print {$self->fh} $self->filter($gcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Extrude perimeters: Decide where to put seams (hide or align seams).
|
||||||
sub _extrude_perimeters {
|
sub _extrude_perimeters {
|
||||||
my ($self, $entities_by_region) = @_;
|
my ($self, $entities_by_region) = @_;
|
||||||
|
|
||||||
@ -595,6 +618,7 @@ sub _extrude_perimeters {
|
|||||||
return $gcode;
|
return $gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Chain the paths hierarchically by a greedy algorithm to minimize a travel distance.
|
||||||
sub _extrude_infill {
|
sub _extrude_infill {
|
||||||
my ($self, $entities_by_region) = @_;
|
my ($self, $entities_by_region) = @_;
|
||||||
|
|
||||||
|
@ -393,6 +393,10 @@ sub make_perimeters {
|
|||||||
for my $i (0 .. ($self->layer_count - 2)) {
|
for my $i (0 .. ($self->layer_count - 2)) {
|
||||||
my $layerm = $self->get_layer($i)->get_region($region_id);
|
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 = $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 $perimeter_spacing = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_spacing;
|
||||||
my $ext_perimeter_flow = $layerm->flow(FLOW_ROLE_EXTERNAL_PERIMETER);
|
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
|
# check whether a portion of the upper slices falls inside the critical area
|
||||||
my $intersection = intersection_ppl(
|
my $intersection = intersection_ppl(
|
||||||
[ map $_->p, @{$upper_layerm->slices} ],
|
$upper_layerm_polygons,
|
||||||
$critical_area,
|
$critical_area,
|
||||||
);
|
);
|
||||||
|
|
||||||
# only add an additional loop if at least 30% of the slice loop would benefit from it
|
# 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;
|
my $total_intersection_length = sum(map $_->length, @$intersection) // 0;
|
||||||
last unless $total_intersection_length > $total_loop_length*0.3;
|
last unless $total_intersection_length > $total_loop_length*0.3;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user