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});
|
||||
}
|
||||
|
||||
# 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) = @_;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user