From e0e2023a5a783e5a631cb8bc4ae79e93c241d0b0 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 19 Feb 2012 10:48:58 +0100 Subject: [PATCH] Duplication is now performed on generated toolpaths instead of mesh (speed boost). #179 --- lib/Slic3r/Extruder.pm | 4 +- lib/Slic3r/ExtrusionPath/Collection.pm | 18 +++--- lib/Slic3r/Print.pm | 80 ++++++++++++++++---------- lib/Slic3r/TriangleMesh.pm | 2 + 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index 61e37a9f0..253810110 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -4,8 +4,8 @@ use Moo; use Slic3r::Geometry qw(scale); has 'layer' => (is => 'rw'); -has 'shift_x' => (is => 'ro', default => sub {0} ); -has 'shift_y' => (is => 'ro', default => sub {0} ); +has 'shift_x' => (is => 'rw', default => sub {0} ); +has 'shift_y' => (is => 'rw', default => sub {0} ); has 'z' => (is => 'rw', default => sub {0} ); has 'print_feed_rate' => (is => 'rw'); diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index 69fb584b4..ab00e4a10 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -25,21 +25,23 @@ sub shortest_path { my $self = shift; my ($start_near) = @_; + my @my_paths = @{$self->paths}; my @paths = (); my $start_at; - CYCLE: while (@{$self->paths}) { + CYCLE: while (@my_paths) { # find nearest point + my $endpoints = [ map $_->endpoints, @my_paths ]; $start_at = $start_near - ? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, $self->endpoints)) + ? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, $endpoints)) : $self->endpoints->[0]; # loop through paths to find the one that starts or ends at the point found - PATH: for (my $i = 0; $i <= $#{$self->paths}; $i++) { - if ($start_at->id eq $self->paths->[$i]->points->[0]->id) { - push @paths, splice @{$self->paths}, $i, 1; - } elsif ($start_at->id eq $self->paths->[$i]->points->[-1]->id) { - $self->paths->[$i]->reverse; - push @paths, splice @{$self->paths}, $i, 1; + PATH: for (my $i = 0; $i <= $#my_paths; $i++) { + if ($start_at->id eq $my_paths[$i]->points->[0]->id) { + push @paths, splice @my_paths, $i, 1; + } elsif ($start_at->id eq $my_paths[$i]->points->[-1]->id) { + $my_paths[$i]->reverse; + push @paths, splice @my_paths, $i, 1; } else { next PATH; } diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index f79aaaee6..8042b752e 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -2,20 +2,16 @@ package Slic3r::Print; use Moo; use Math::ConvexHull 1.0.4 qw(convex_hull); -use Slic3r::Geometry qw(X Y Z PI MIN MAX scale); +use Slic3r::Geometry qw(X Y Z PI MIN MAX scale unscale move_points); use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex union_ex offset JT_ROUND JT_MITER); use XXX; -has 'x_length' => ( - is => 'ro', - required => 1, -); - -has 'y_length' => ( - is => 'ro', - required => 1, -); +has 'x_length' => (is => 'ro', required => 1); +has 'y_length' => (is => 'ro', required => 1); +has 'total_x_length' => (is => 'rw'); # including duplicates +has 'total_y_length' => (is => 'rw'); # including duplicates +has 'copies' => (is => 'rw', default => sub {[]}); has 'layers' => ( traits => ['Array'], @@ -41,14 +37,6 @@ sub new_from_mesh { $mesh->move(@shift); } - # duplicate object - { - my @size = $mesh->size; - my @duplicate_offset = map +($size[$_] + scale $Slic3r::duplicate_distance), (X,Y); - $mesh->duplicate(map [$duplicate_offset[X] * ($_-1), 0], 2..$Slic3r::duplicate_x); - $mesh->duplicate(map [0, $duplicate_offset[Y] * ($_-1)], 2..$Slic3r::duplicate_y); - } - # initialize print job my @size = $mesh->size; my $print = $class->new( @@ -138,6 +126,24 @@ sub new_from_mesh { return $print; } +sub BUILD { + my $self = shift; + + my $dist = scale $Slic3r::duplicate_distance; + $self->total_x_length($self->x_length * $Slic3r::duplicate_x + $dist * ($Slic3r::duplicate_x - 1)); + $self->total_y_length($self->y_length * $Slic3r::duplicate_y + $dist * ($Slic3r::duplicate_y - 1)); + + # generate offsets for copies + for my $x_copy (1..$Slic3r::duplicate_x) { + for my $y_copy (1..$Slic3r::duplicate_y) { + push @{$self->copies}, [ + ($self->x_length + scale $Slic3r::duplicate_distance) * ($x_copy-1), + ($self->y_length + scale $Slic3r::duplicate_distance) * ($y_copy-1), + ]; + } + } +} + sub layer_count { my $self = shift; return scalar @{ $self->layers }; @@ -339,6 +345,9 @@ sub extrude_skirt { ); return if !@points; + # duplicate points to take copies into account + push @points, map move_points($_, @points), @{$self->copies}; + # find out convex hull my $convex_hull = convex_hull(\@points); @@ -480,30 +489,39 @@ sub export_gcode { print $fh "M82 ; use absolute distances for extrusion\n"; } - # set up our extruder object - my $extruder = Slic3r::Extruder->new( - # calculate X,Y shift to center print around specified origin - shift_x => $Slic3r::print_center->[X] - ($self->x_length * $Slic3r::resolution / 2), - shift_y => $Slic3r::print_center->[Y] - ($self->y_length * $Slic3r::resolution / 2), + # calculate X,Y shift to center print around specified origin + my @shift = ( + $Slic3r::print_center->[X] - (unscale $self->total_x_length / 2), + $Slic3r::print_center->[Y] - (unscale $self->total_y_length / 2), ); + # set up our extruder object + my $extruder = Slic3r::Extruder->new; + # write gcode commands layer by layer foreach my $layer (@{ $self->layers }) { # go to layer print $fh $extruder->change_layer($layer); # extrude skirts + $extruder->shift_x($shift[X]); + $extruder->shift_y($shift[Y]); print $fh $extruder->set_acceleration($Slic3r::perimeter_acceleration); print $fh $extruder->extrude_loop($_, 'skirt') for @{ $layer->skirts }; - # extrude perimeters - print $fh $extruder->extrude($_, 'perimeter') for @{ $layer->perimeters }; - - # extrude fills - print $fh $extruder->set_acceleration($Slic3r::infill_acceleration); - for my $fill (@{ $layer->fills }) { - print $fh $extruder->extrude_path($_, 'fill') - for $fill->shortest_path($extruder->last_pos); + foreach my $copy (@{$self->copies}) { + $extruder->shift_x($shift[X] + unscale $copy->[X]); + $extruder->shift_y($shift[Y] + unscale $copy->[Y]); + + # extrude perimeters + print $fh $extruder->extrude($_, 'perimeter') for @{ $layer->perimeters }; + + # extrude fills + print $fh $extruder->set_acceleration($Slic3r::infill_acceleration); + for my $fill (@{ $layer->fills }) { + print $fh $extruder->extrude_path($_, 'fill') + for $fill->shortest_path($extruder->last_pos); + } } } diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index 89835d179..fb5d22c92 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -16,6 +16,7 @@ has 'edges_facets' => (is => 'ro', default => sub { [] }); # id => [ $f1_id, $f use constant MIN => 0; use constant MAX => 1; +# always make sure BUILD is idempotent sub BUILD { my $self = shift; @@ -303,6 +304,7 @@ sub duplicate { } } push @{$self->facets}, @new_facets; + $self->BUILD; } sub bounding_box {