use Test::More tests => 12; use strict; use warnings; BEGIN { use FindBin; use lib "$FindBin::Bin/../lib"; use local::lib "$FindBin::Bin/../local-lib"; } use Data::Dumper; use List::Util qw(first); use Slic3r; use Slic3r::Geometry qw(epsilon scale PI); use Slic3r::Geometry::Clipper qw(diff); use Slic3r::Test; { my $config = Slic3r::Config->new_from_defaults; $config->set('support_material', 1); my @contact_z = my @top_z = (); my $test = sub { my $print = Slic3r::Test::init_print('20mm_cube', config => $config); my $flow = $print->print->objects->[0]->support_material_flow; my $support = Slic3r::Print::SupportMaterial->new( object_config => $print->print->objects->[0]->config, print_config => $print->print->config, flow => $flow, interface_flow => $flow, first_layer_flow => $flow, ); my $support_z = $support->support_layers_z(\@contact_z, \@top_z, $config->layer_height); my $expected_top_spacing = $support->contact_distance($config->layer_height, $config->nozzle_diameter->[0]); diag(Dumper($support_z)); is $support_z->[0], $config->first_layer_height, 'first layer height is honored'; is scalar(grep { $support_z->[$_]-$support_z->[$_-1] <= 0 } 1..$#$support_z), 0, 'no null or negative support layers'; is scalar(grep { $support_z->[$_]-$support_z->[$_-1] > $config->nozzle_diameter->[0] + epsilon } 1..$#$support_z), 0, 'no layers thicker than nozzle diameter'; my $wrong_top_spacing = 0; foreach my $top_z (@top_z) { # find layer index of this top surface my $layer_id = first { abs($support_z->[$_] - $top_z) < epsilon } 0..$#$support_z; # check that first support layer above this top surface (or the next one) is spaced with nozzle diameter $wrong_top_spacing = 1 if ($support_z->[$layer_id+1] - $support_z->[$layer_id]) != $expected_top_spacing && ($support_z->[$layer_id+2] - $support_z->[$layer_id]) != $expected_top_spacing; } ok !$wrong_top_spacing, 'layers above top surfaces are spaced correctly'; }; $config->set('layer_height', 0.2); $config->set('first_layer_height', 0.3); @contact_z = (1.9); @top_z = (1.1); $test->(); $config->set('first_layer_height', 0.4); $test->(); $config->set('layer_height', $config->nozzle_diameter->[0]); $test->(); } # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('raft_layers', 3); # $config->set('brim_width', 0); # $config->set('skirts', 0); # $config->set('support_material_extruder', 2); # $config->set('support_material_interface_extruder', 2); # $config->set('layer_height', 0.4); # $config->set('first_layer_height', 0.4); # my $print = Slic3r::Test::init_print('overhang', config => $config); # ok my $gcode = Slic3r::Test::gcode($print), 'no conflict between raft/support and brim'; # # my $tool = 0; # Slic3r::GCode::Reader->new->parse($gcode, sub { # my ($self, $cmd, $args, $info) = @_; # # if ($cmd =~ /^T(\d+)/) { # $tool = $1; # } elsif ($info->{extruding}) { # if ($self->Z <= ($config->raft_layers * $config->layer_height)) { # fail 'not extruding raft with support material extruder' # if $tool != ($config->support_material_extruder-1); # } else { # fail 'support material exceeds raft layers' # if $tool == $config->support_material_extruder-1; # # TODO: we should test that full support is generated when we use raft too # } # } # }); #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('skirts', 0); # $config->set('raft_layers', 3); # $config->set('support_material_pattern', 'honeycomb'); # $config->set('support_material_extrusion_width', 0.6); # $config->set('first_layer_extrusion_width', '100%'); # $config->set('bridge_speed', 99); # $config->set('cooling', 0); # prevent speed alteration # $config->set('first_layer_speed', '100%'); # prevent speed alteration # $config->set('start_gcode', ''); # prevent any unexpected Z move # my $print = Slic3r::Test::init_print('20mm_cube', config => $config); # # my $layer_id = -1; # so that first Z move sets this to 0 # my @raft = my @first_object_layer = (); # my %first_object_layer_speeds = (); # F => 1 # Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { # my ($self, $cmd, $args, $info) = @_; # if ($info->{extruding} && $info->{dist_XY} > 0) { # if ($layer_id <= $config->raft_layers) { # # this is a raft layer or the first object layer # my $line = Slic3r::Line->new_scale([ $self->X, $self->Y ], [ $info->{new_X}, $info->{new_Y} ]); # my @path = @{$line->grow(scale($config->support_material_extrusion_width/2))}; # if ($layer_id < $config->raft_layers) { # # this is a raft layer # push @raft, @path; # } else { # push @first_object_layer, @path; # $first_object_layer_speeds{ $args->{F} // $self->F } = 1; # } # } # } elsif ($cmd eq 'G1' && $info->{dist_Z} > 0) { # $layer_id++; # } # }); # # ok !@{diff(\@first_object_layer, \@raft)}, # 'first object layer is completely supported by raft'; # is scalar(keys %first_object_layer_speeds), 1, # 'only one speed used in first object layer'; # ok +(keys %first_object_layer_speeds)[0] == $config->bridge_speed*60, # 'bridge speed used in first object layer'; #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('layer_height', 0.2); # $config->set('skirts', 0); # $config->set('raft_layers', 5); # $config->set('support_material_pattern', 'rectilinear'); # $config->set('support_material_extrusion_width', 0.4); # $config->set('support_material_interface_extrusion_width', 0.6); # $config->set('support_material_interface_layers', 2); # $config->set('first_layer_extrusion_width', '100%'); # $config->set('bridge_speed', 99); # $config->set('cooling', 0); # prevent speed alteration # $config->set('first_layer_speed', '100%'); # prevent speed alteration # $config->set('start_gcode', ''); # prevent any unexpected Z move # my $print = Slic3r::Test::init_print('20mm_cube', config => $config); # # my $layer_id = -1; # my $success = 1; # Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { # my ($self, $cmd, $args, $info) = @_; # if ($info->{extruding} && $info->{dist_XY} > 0) { # # this is a raft layer # if (($layer_id < $config->raft_layers) && ($layer_id > 0)) { # my $width; # my $support_layer_height = $config->nozzle_diameter->[0] * 0.75; # # # support layer # if ($config->raft_layers - $config->support_material_interface_layers > $layer_id) { # $width = $config->support_material_extrusion_width; # } # # interface layer # else { # $width = $config->support_material_interface_extrusion_width; # } # my $expected_E_per_mm3 = 4 / (($config->filament_diameter->[0]**2) * PI); # my $expected_mm3_per_mm = $width * $support_layer_height + ($support_layer_height**2) / 4.0 * (PI-4.0); # my $expected_e_per_mm = $expected_E_per_mm3 * $expected_mm3_per_mm; # # my $e_per_mm = ($info->{dist_E} / $info->{dist_XY});; # # my $diff = abs($e_per_mm - $expected_e_per_mm); # # if ($diff > 0.001) { # $success = 0; # } # } # } elsif ($cmd eq 'G1' && $info->{dist_Z} > 0) { # $layer_id++; # } # }); # # ok $success, # 'support material interface extrusion width is used for interfaces'; #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('skirts', 0); # $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 $test = sub { # my ($raft_layers) = @_; # $config->set('raft_layers', $raft_layers); # 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'; # }; # # $test->(2); # $test->(70); # # $config->set('layer_height', 0.4); # $config->set('first_layer_height', 0.35); # $test->(3); # $test->(70); #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('brim_width', 0); # $config->set('skirts', 0); # $config->set('support_material', 1); # $config->set('top_solid_layers', 0); # so that we don't have the internal bridge over infill # $config->set('bridge_speed', 99); # $config->set('cooling', 0); # $config->set('first_layer_speed', '100%'); # # my $test = sub { # my $print = Slic3r::Test::init_print('overhang', config => $config); # # my $has_bridge_speed = 0; # Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { # my ($self, $cmd, $args, $info) = @_; # # if ($info->{extruding}) { # if (($args->{F} // $self->F) == $config->bridge_speed*60) { # $has_bridge_speed = 1; # } # } # }); # return $has_bridge_speed; # }; # # $config->set('support_material_contact_distance', 0.2); # ok $test->(), 'bridge speed is used when support_material_contact_distance > 0'; # # $config->set('support_material_contact_distance', 0); # ok !$test->(), 'bridge speed is not used when support_material_contact_distance == 0'; # # $config->set('raft_layers', 5); # $config->set('support_material_contact_distance', 0.2); # ok $test->(), 'bridge speed is used when raft_layers > 0 and support_material_contact_distance > 0'; # # $config->set('support_material_contact_distance', 0); # ok !$test->(), 'bridge speed is not used when raft_layers > 0 and support_material_contact_distance == 0'; #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('skirts', 0); # $config->set('start_gcode', ''); # $config->set('raft_layers', 8); # $config->set('nozzle_diameter', [0.4, 1]); # $config->set('layer_height', 0.1); # $config->set('first_layer_height', 0.8); # $config->set('support_material_extruder', 2); # $config->set('support_material_interface_extruder', 2); # $config->set('support_material_contact_distance', 0); # my $print = Slic3r::Test::init_print('20mm_cube', config => $config); # ok my $gcode = Slic3r::Test::gcode($print), 'first_layer_height is validated with support material extruder nozzle diameter when using raft layers'; # # my $tool = undef; # my @z = (0); # my %layer_heights_by_tool = (); # tool => [ lh, lh... ] # Slic3r::GCode::Reader->new->parse($gcode, sub { # my ($self, $cmd, $args, $info) = @_; # # if ($cmd =~ /^T(\d+)/) { # $tool = $1; # } elsif ($cmd eq 'G1' && exists $args->{Z} && $args->{Z} != $self->Z) { # push @z, $args->{Z}; # } elsif ($info->{extruding} && $info->{dist_XY} > 0) { # $layer_heights_by_tool{$tool} ||= []; # push @{ $layer_heights_by_tool{$tool} }, $z[-1] - $z[-2]; # } # }); # # ok !defined(first { $_ > $config->nozzle_diameter->[0] + epsilon } # @{ $layer_heights_by_tool{$config->perimeter_extruder-1} }), # 'no object layer is thicker than nozzle diameter'; # # ok !defined(first { abs($_ - $config->layer_height) < epsilon } # @{ $layer_heights_by_tool{$config->support_material_extruder-1} }), # 'no support material layer is as thin as object layers'; #} # #{ # my $config = Slic3r::Config->new_from_defaults; # $config->set('support_material_enforce_layers', 100); # $config->set('support_material', 0); # my @contact_z = my @top_z = (); # # my $test = sub { # my $print = Slic3r::Test::init_print('20mm_cube', config => $config); # my $flow = $print->print->objects->[0]->support_material_flow; # my $support = Slic3r::Print::SupportMaterial->new( # object_config => $print->print->objects->[0]->config, # print_config => $print->print->config, # flow => $flow, # interface_flow => $flow, # first_layer_flow => $flow, # ); # my $support_z = $support->support_layers_z(\@contact_z, \@top_z, $config->layer_height); # # is scalar(grep { $support_z->[$_]-$support_z->[$_-1] <= 0 } 1..$#$support_z), 0, # 'forced support is generated'; # # }; # $config->set('layer_height', 0.2); # $config->set('first_layer_height', 0.3); # @contact_z = (1.9); # @top_z = (1.1); # $test->(); #} __END__