diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 612eb8555..74427e63d 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -127,17 +127,30 @@ sub slice { # make layers taking custom heights into account my $print_z = my $slice_z = my $height = my $id = 0; + my $first_object_layer_height = -1; # add raft layers if ($self->config->raft_layers > 0) { + $id += $self->config->raft_layers; + + # raise first object layer Z by the thickness of the raft itself + # plus the extra distance required by the support material logic $print_z += $self->config->get_value('first_layer_height'); $print_z += $self->config->layer_height * ($self->config->raft_layers - 1); - $id += $self->config->raft_layers; + + # at this stage we don't know which nozzles are actually used for the first layer + # so we compute the average of all of them + my $nozzle_diameter = sum(@{$self->print->config->nozzle_diameter})/@{$self->print->config->nozzle_diameter}; + my $distance = Slic3r::Print::SupportMaterial::contact_distance($nozzle_diameter); + + # force first layer print_z according to the contact distance + # (the loop below will raise print_z by such height) + $first_object_layer_height = $distance; } # loop until we have at least one layer and the max slice_z reaches the object height my $max_z = unscale($self->size->z); - while (!@{$self->layers} || ($slice_z - $height) <= $max_z) { + while (($slice_z - $height) <= $max_z) { # assign the default height to the layer according to the general settings $height = ($id == 0) ? $self->config->get_value('first_layer_height') @@ -153,7 +166,11 @@ sub slice { next; } } - + + if ($first_object_layer_height != -1 && !@{$self->layers}) { + $height = $first_object_layer_height; + } + $print_z += $height; $slice_z += $height/2; diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index d58a05d68..712d09ab0 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -190,7 +190,7 @@ sub contact_area { @{$layer->regions}; my $nozzle_diameter = sum(@nozzle_diameters)/@nozzle_diameters; - my $contact_z = $layer->print_z - $nozzle_diameter * 1.5; + my $contact_z = $layer->print_z - contact_distance($nozzle_diameter); ###$contact_z = $layer->print_z - $layer->height; # ignore this contact area if it's too low @@ -739,4 +739,10 @@ sub overlapping_layers { } 0..$#$support_z; } +# class method +sub contact_distance { + my ($nozzle_diameter) = @_; + return $nozzle_diameter * 1.5; +} + 1; diff --git a/t/support.t b/t/support.t index a1e7173d9..402ea33e8 100644 --- a/t/support.t +++ b/t/support.t @@ -1,4 +1,4 @@ -use Test::More tests => 14; +use Test::More tests => 15; use strict; use warnings; @@ -129,4 +129,31 @@ use Slic3r::Test; 'first object layer is completely supported by raft'; } +{ + my $config = Slic3r::Config->new_from_defaults; + $config->set('skirts', 0); + $config->set('raft_layers', 2); + $config->set('layer_height', 0.35); + $config->set('first_layer_height', 0.3); + $config->set('nozzle_diameter', [0.5]); + $config->set('support_material_extruder', 2); + $config->set('support_material_interface_extruder', 2); + my $print = Slic3r::Test::init_print('20mm_cube', config => $config); + my %raft_z = (); # z => 1 + my $tool = undef; + Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { + my ($self, $cmd, $args, $info) = @_; + + if ($cmd =~ /^T(\d+)/) { + $tool = $1; + } elsif ($info->{extruding} && $info->{dist_XY} > 0) { + if ($tool == $config->support_material_extruder-1) { + $raft_z{$self->Z} = 1; + } + } + }); + + is scalar(keys %raft_z), $config->raft_layers, 'correct number of raft layers is generated'; +} + __END__