Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Slic3r.pm1
-rw-r--r--lib/Slic3r/ExtrusionLoop.pm31
-rw-r--r--lib/Slic3r/ExtrusionPath.pm19
-rw-r--r--lib/Slic3r/Geometry.pm29
-rw-r--r--lib/Slic3r/Perimeter.pm48
-rw-r--r--lib/Slic3r/Polyline.pm15
-rw-r--r--lib/Slic3r/Print.pm16
7 files changed, 113 insertions, 46 deletions
diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm
index 3185c24d8..d9db1381b 100644
--- a/lib/Slic3r.pm
+++ b/lib/Slic3r.pm
@@ -8,6 +8,7 @@ sub debugf {
printf @_ if $debug;
}
+use Slic3r::ExtrusionLoop;
use Slic3r::ExtrusionPath;
use Slic3r::Fill;
use Slic3r::Geometry;
diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm
new file mode 100644
index 000000000..2503c77d8
--- /dev/null
+++ b/lib/Slic3r/ExtrusionLoop.pm
@@ -0,0 +1,31 @@
+package Slic3r::ExtrusionLoop;
+use Moo;
+
+use XXX;
+
+extends 'Slic3r::Polyline::Closed';
+
+sub split_at {
+ my $self = shift;
+ my ($point) = @_;
+
+ $point = Slic3r::Point->cast($point);
+
+ # find index of point
+ my $i = -1;
+ for (my $n = 0; $n <= $#{$self->points}; $n++) {
+ if ($point->id eq $self->points->[$n]->id) {
+ $i = $n;
+ last;
+ }
+ }
+ die "Point not found" if $i == -1;
+
+ my @new_points = ();
+ push @new_points, @{$self->points}[$i .. $#{$self->points}];
+ push @new_points, @{$self->points}[0 .. $i];
+
+ return Slic3r::ExtrusionPath->new(points => [@new_points]);
+}
+
+1;
diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm
index 43802db9e..8df519789 100644
--- a/lib/Slic3r/ExtrusionPath.pm
+++ b/lib/Slic3r/ExtrusionPath.pm
@@ -3,4 +3,23 @@ use Moo;
extends 'Slic3r::Polyline';
+sub clip_end {
+ my $self = shift;
+ my ($distance) = @_;
+
+ while ($distance > 0) {
+ my $last_point = pop @{$self->points};
+
+ my $last_segment_length = $last_point->distance_to($self->points->[-1]);
+ if ($last_segment_length <= $distance) {
+ $distance -= $last_segment_length;
+ next;
+ }
+
+ my $new_point = Slic3r::Geometry::point_along_segment($last_point->p, $self->points->[-1]->p, $distance);
+ push @{$self->points}, Slic3r::Point->cast($new_point);
+ $distance = 0;
+ }
+}
+
1;
diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm
index 92a69716f..f81e67122 100644
--- a/lib/Slic3r/Geometry.pm
+++ b/lib/Slic3r/Geometry.pm
@@ -115,4 +115,33 @@ sub polygon_lines {
return @lines;
}
+sub nearest_point {
+ my ($point, $points) = @_;
+
+ my ($nearest_point, $distance);
+ foreach my $p (@$points) {
+ my $d = distance_between_points($point, $p);
+ if (!defined $distance || $d < $distance) {
+ $nearest_point = $p;
+ $distance = $d;
+ }
+ }
+ return $nearest_point;
+}
+
+sub point_along_segment {
+ my ($p1, $p2, $distance) = @_;
+
+ my $point = [ @$p1 ];
+
+ my $line_length = sqrt( (($p2->[X] - $p1->[X])**2) + (($p2->[Y] - $p1->[Y])**2) );
+ for (X, Y) {
+ if ($p1->[$_] != $p2->[$_]) {
+ $point->[$_] = $p1->[$_] + ($p2->[$_] - $p1->[$_]) * $distance / $line_length;
+ }
+ }
+
+ return $point;
+}
+
1;
diff --git a/lib/Slic3r/Perimeter.pm b/lib/Slic3r/Perimeter.pm
index 723a9b1b0..69c49e1fd 100644
--- a/lib/Slic3r/Perimeter.pm
+++ b/lib/Slic3r/Perimeter.pm
@@ -58,40 +58,18 @@ sub make_perimeter {
), $self->offset_polygon($perimeters[-1]),
}
- # generate paths for holes
+ # generate paths for holes:
# we start from innermost loops (that is, external ones), do them
# for all holes, than go on with inner loop and do that for all
- # holes and so on
- foreach my $hole (map @$_, values %holes) {
- my @points = @$hole;
- push @points, [ @{$points[0]} ];
- # to avoid blobs, the first point is replaced by the point of
- # the segment which is $Slic3r::flow_width / $Slic3r::resolution
- # away from it to avoid the extruder to get two times there
- $points[0] = $self->_get_point_along_line($points[0], $points[1],
- $Slic3r::flow_width / $Slic3r::resolution);
- push @{ $layer->perimeters }, Slic3r::ExtrusionPath->cast([@points]);
- }
-
- # generate paths for contours
+ # holes and so on;
+ # then we generate paths for contours:
# this time we do something different: we do contour loops for one
# shape (that is, one original surface) at a time: we start from the
# innermost loop (that is, internal one), then without interrupting
# our path we go onto the outer loop and continue; this should ensure
# good surface quality
- foreach my $polylines (values %contours) {
- my @path_points = ();
- foreach my $p (map $self->_mgp_from_points_ref($_), @$polylines) {
- my $points = $p->points;
- # to avoid blobs, the first point is replaced by the point of
- # the segment which is $Slic3r::flow_width / $Slic3r::resolution
- # away from it to avoid the extruder to get two times there
- push @$points, [ @{$points->[0]} ];
- $points->[0] = $self->_get_point_along_line($points->[0], $points->[1],
- $Slic3r::flow_width / $Slic3r::resolution);
- push @path_points, @$points;
- }
- push @{ $layer->perimeters }, Slic3r::ExtrusionPath->cast([ reverse @path_points ]);
+ foreach my $p (map @$_, values %holes, values %contours) {
+ push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($p);
}
# generate skirt on bottom layer
@@ -158,20 +136,4 @@ sub _mgp_from_polygons_ref {
return $p;
}
-sub _get_point_along_line {
- my $self = shift;
- my ($p1, $p2, $distance) = @_;
-
- my $point = [ @$p1 ];
-
- my $line_length = sqrt( (($p2->[X] - $p1->[X])**2) + (($p2->[Y] - $p1->[Y])**2) );
- for (X, Y) {
- if ($p1->[$_] != $p2->[$_]) {
- $point->[$_] = $p1->[$_] + ($p2->[$_] - $p1->[$_]) * $distance / $line_length;
- }
- }
-
- return $point;
-}
-
1;
diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm
index c10cf21b0..afb6d90c1 100644
--- a/lib/Slic3r/Polyline.pm
+++ b/lib/Slic3r/Polyline.pm
@@ -18,11 +18,11 @@ sub id {
}
sub cast {
- my $self = shift;
+ my $class = shift;
my ($points) = @_;
@$points = map { ref $_ eq 'ARRAY' ? Slic3r::Point->cast($_) : $_ } @$points;
- return __PACKAGE__->new(points => $points);
+ return $class->new(points => $points);
}
sub lines {
@@ -82,4 +82,15 @@ sub make_clockwise {
$self->reverse_points if $self->is_counter_clockwise;
}
+sub nearest_point_to {
+ my $self = shift;
+ my ($point) = @_;
+
+ # get point as arrayref
+ $point = ref $point eq 'ARRAY' ? $point : $point->p;
+
+ $point = Slic3r::Geometry::nearest_point($point, $self->p);
+ return Slic3r::Point->cast($point);
+}
+
1;
diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm
index dc9f7ac73..cd2fedcce 100644
--- a/lib/Slic3r/Print.pm
+++ b/lib/Slic3r/Print.pm
@@ -183,6 +183,7 @@ sub export_gcode {
# make up a subroutine to generate G1 commands
my $extrusion_distance = 0;
+ my $last_pos; # on XY plane
my $G1 = sub {
my ($point, $z, $e, $comment) = @_;
printf $fh "G1";
@@ -191,6 +192,7 @@ sub export_gcode {
printf $fh " X%.${dec}f Y%.${dec}f",
($point->x * $Slic3r::resolution) + $shift[X],
($point->y * $Slic3r::resolution) + $shift[Y]; #**
+ $last_pos = $point->p;
}
if ($z) {
printf $fh " Z%.${dec}f", $z;
@@ -269,7 +271,19 @@ sub export_gcode {
$Extrude->($_, 'skirt') for @{ $layer->skirts };
# extrude perimeters
- $Extrude->($_, 'perimeter') for @{ $layer->perimeters };
+ for my $loop (@{ $layer->perimeters }) {
+ # find the point of the loop that is closest to the current extruder position
+ my $start_at = $last_pos ? $loop->nearest_point_to($last_pos) : $loop->points->[0];
+
+ # split the loop at the starting point and make a path
+ my $extrusion_path = $loop->split_at($start_at);
+
+ # clip the path to avoid the extruder to get exactly on the first point of the loop
+ $extrusion_path->clip_end($Slic3r::flow_width / $Slic3r::resolution);
+
+ # extrude along the path
+ $Extrude->($extrusion_path, 'perimeter')
+ }
# extrude fills
$Extrude->($_, 'fill') for @{ $layer->fills };