diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 69d2765aa..8062b7d6b 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -97,7 +97,7 @@ sub extrude_loop { # extrude all loops ccw $loop = $loop->unpack if $loop->isa('Slic3r::ExtrusionLoop::Packed'); - $loop->polygon->make_counter_clockwise; + my $was_clockwise = $loop->polygon->make_counter_clockwise; # find the point of the loop that is closest to the current extruder position # or randomize if requested @@ -118,7 +118,27 @@ sub extrude_loop { return '' if !@{$extrusion_path->polyline}; # extrude along the path - return $self->extrude_path($extrusion_path, $description); + my $gcode = $self->extrude_path($extrusion_path, $description); + + # make a little move inwards before leaving loop + if ($loop->role == EXTR_ROLE_EXTERNAL_PERIMETER) { + # detect angle between last and first segment + # the side depends on the original winding order of the polygon (left for contours, right for holes) + my @points = $was_clockwise ? (-2, 1) : (1, -2); + my $angle = Slic3r::Geometry::angle3points(@{$extrusion_path->polyline}[0, @points]) / 3; + $angle *= -1 if $was_clockwise; + + # create the destination point along the first segment and rotate it + my $point = Slic3r::Geometry::point_along_segment(@{$extrusion_path->polyline}[0,1], scale $extrusion_path->flow_spacing); + bless $point, 'Slic3r::Point'; + $point->rotate($angle, $extrusion_path->polyline->[0]); + + # generate the travel move + $self->speed('travel'); + $gcode .= $self->G0($point, undef, 0, "move inwards before travel"); + } + + return $gcode; } sub extrude_path { diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index 9bfb0bced..db3ecb6c8 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -736,6 +736,7 @@ sub size_3D { return map $extents[$_][MAX] - $extents[$_][MIN], (X,Y,Z); } +# this assumes a CCW rotation from $p2 to $p3 around $p1 sub angle3points { my ($p1, $p2, $p3) = @_; # p1 is the center diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 50805ab47..eaaca1d0f 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -31,12 +31,20 @@ sub is_counter_clockwise { sub make_counter_clockwise { my $self = shift; - $self->reverse if !$self->is_counter_clockwise; + if (!$self->is_counter_clockwise) { + $self->reverse; + return 1; + } + return 0; } sub make_clockwise { my $self = shift; - $self->reverse if $self->is_counter_clockwise; + if ($self->is_counter_clockwise) { + $self->reverse; + return 1; + } + return 0; } sub merge_continuous_lines { diff --git a/t/angles.t b/t/angles.t index 0caac718d..dc1a671b0 100644 --- a/t/angles.t +++ b/t/angles.t @@ -2,7 +2,7 @@ use Test::More; use strict; use warnings; -plan tests => 24; +plan tests => 26; BEGIN { use FindBin; @@ -10,7 +10,7 @@ BEGIN { } use Slic3r; -use Slic3r::Geometry qw(line_atan line_direction rad2deg_dir PI); +use Slic3r::Geometry qw(line_atan line_direction rad2deg_dir angle3points PI); #========================================================== @@ -54,3 +54,10 @@ use Slic3r::Geometry qw(line_atan line_direction rad2deg_dir PI); } #========================================================== + +{ + is angle3points([0,0], [10,0], [0,10]), PI/2, 'CW angle3points'; + is angle3points([0,0], [0,10], [10,0]), PI/2*3, 'CCW angle3points'; +} + +#==========================================================