From b246480535586a74e72c87ed11c792ca256c7622 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 19 May 2012 17:57:38 +0200 Subject: [PATCH] Massive reduction of memory usage (down to one third). --- lib/Slic3r.pm | 2 +- lib/Slic3r/Extruder.pm | 2 ++ lib/Slic3r/ExtrusionLoop.pm | 8 ++++++- lib/Slic3r/ExtrusionPath.pm | 8 ++++++- lib/Slic3r/ExtrusionPath/Collection.pm | 1 + lib/Slic3r/Geometry.pm | 2 +- lib/Slic3r/Layer.pm | 29 ++++++---------------- lib/Slic3r/Polyline.pm | 16 +++++++++++++ lib/Slic3r/Print.pm | 5 ---- t/serialize.t | 33 ++++++++++++++++++++++++++ 10 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 t/serialize.t diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 554028496..df3fed9b7 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -80,7 +80,7 @@ our $perimeter_acceleration = 25; # mm/s^2 our $infill_acceleration = 50; # mm/s^2 # accuracy options -our $scaling_factor = 0.00000001; +our $scaling_factor = 0.000001; our $resolution = 0.01; our $small_perimeter_length = (6.5 / $scaling_factor)*2*PI; our $layer_height = 0.4; diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index afacbd4f3..d9bb76678 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -78,6 +78,7 @@ sub extrude_loop { my ($loop, $description) = @_; # extrude all loops ccw + $loop->deserialize; $loop->polygon->make_counter_clockwise; # find the point of the loop that is closest to the current extruder position @@ -85,6 +86,7 @@ sub extrude_loop { # split the loop at the starting point and make a path my $extrusion_path = $loop->split_at($start_at); + $extrusion_path->deserialize; # clip the path to avoid the extruder to get exactly on the first point of the loop; # if polyline was shorter than the clipping distance we'd get a null polyline, so diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index 5f00906cc..da5be8985 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -3,7 +3,7 @@ use Moo; # the underlying Slic3r::Polygon objects holds the geometry has 'polygon' => ( - is => 'ro', + is => 'rw', required => 1, handles => [qw(is_printable nearest_point_to)], ); @@ -14,6 +14,12 @@ has 'role' => (is => 'rw', required => 1); sub BUILD { my $self = shift; bless $self->polygon, 'Slic3r::Polygon'; + $self->polygon($self->polygon->serialize); +} + +sub deserialize { + my $self = shift; + $self->polygon($self->polygon->deserialize); } sub split_at { diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 832f1c589..756594d2a 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -11,7 +11,7 @@ use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); # the underlying Slic3r::Polyline objects holds the geometry has 'polyline' => ( - is => 'ro', + is => 'rw', required => 1, handles => [qw(merge_continuous_lines lines length)], ); @@ -34,6 +34,12 @@ use constant EXTR_ROLE_SUPPORTMATERIAL => 6; sub BUILD { my $self = shift; bless $self->polyline, 'Slic3r::Polyline'; + $self->polyline($self->polyline->serialize); +} + +sub deserialize { + my $self = shift; + $self->polyline($self->polyline->deserialize); } sub clip_end { diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index 595e3105d..9f29833ea 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -25,6 +25,7 @@ sub shortest_path { my ($start_near) = @_; my @my_paths = @{$self->paths}; + $_->deserialize for @my_paths; my @paths = (); my $start_at; CYCLE: while (@my_paths) { diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index 304a0fecf..989f98659 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -236,7 +236,7 @@ sub polyline_lines { } sub polygon_lines { - my ($polygon) = @_; + my ($polygon) = @_;use XXX; ZZZ $polygon if !eval { @$polygon }; return polyline_lines([ @$polygon, $polygon->[0] ]); } diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index e3529ed75..d4cd4a3c3 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -284,19 +284,14 @@ sub make_perimeters { } } - foreach my $hole (reverse @holes) { - push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $hole, role => EXTR_ROLE_PERIMETER); + # do holes, then contours starting from innermost one + foreach my $polygon ((reverse @holes), (map $_->contour, map @$_, reverse @$island)) { + next unless $polygon->is_printable; + push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new( + polygon => $polygon, + role => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : EXTR_ROLE_PERIMETER, + ); } - - # do contours starting from innermost one - foreach my $contour (map $_->contour, map @$_, reverse @$island) { - push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $contour, role => EXTR_ROLE_PERIMETER); - } - } - - # detect small perimeters by checking their area - for (@{ $self->perimeters }) { - $_->role(EXTR_ROLE_SMALLPERIMETER) if abs($_->polygon->length) <= $Slic3r::small_perimeter_length; } # add thin walls as perimeters @@ -384,16 +379,6 @@ sub remove_small_surfaces { } } -sub remove_small_perimeters { - my $self = shift; - my @good_perimeters = grep $_->is_printable, @{$self->perimeters}; - Slic3r::debugf "removed %d unprintable perimeters at layer %d\n", - (@{$self->perimeters} - @good_perimeters), $self->id - if @good_perimeters != @{$self->perimeters}; - - @{$self->perimeters} = @good_perimeters; -} - # make bridges printable sub process_bridges { my $self = shift; diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 10084e81d..a6cb91af8 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -21,6 +21,22 @@ sub new { $self; } +sub serialize { + my $self = shift; + my $s = \ pack 'l*', map @$_, @$self; + bless $s, ref $self; + return $s; +} + +sub deserialize { + my $self = shift; + my @v = unpack '(l2)*', $$self; + my $o = [ map [ $v[2*$_], $v[2*$_+1] ], 0 .. int($#v/2) ]; + bless $_, 'Slic3r::Point' for @$o; + bless $o, ref $self; + return $o; +} + sub id { my $self = shift; return join ' - ', sort map $_->id, @$self; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index c064ee68b..d3975ebb8 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -188,11 +188,6 @@ sub export_gcode { $status_cb->(45, "Detect bridges"); $_->process_bridges for map @{$_->layers}, @{$self->objects}; - # this will remove unprintable perimeter loops - # (those that are too tight for extrusion) - $status_cb->(50, "Cleaning up the perimeters"); - $_->remove_small_perimeters for map @{$_->layers}, @{$self->objects}; - # detect which fill surfaces are near external layers # they will be split in internal and internal-solid surfaces $status_cb->(60, "Generating horizontal shells"); diff --git a/t/serialize.t b/t/serialize.t new file mode 100644 index 000000000..eac51d160 --- /dev/null +++ b/t/serialize.t @@ -0,0 +1,33 @@ +use Test::More; +use strict; +use warnings; + +plan tests => 2; + +BEGIN { + use FindBin; + use lib "$FindBin::Bin/../lib"; +} + +use Slic3r; +use Slic3r::Geometry qw(scale); + +#========================================================== + +{ + my $points = [ + [226,701], [260,681], [109,420], [149,397], [300,658], [308,654], + ]; + foreach my $point (@$points) { + @$point = map scale $_, @$point; + } + my $polyline = Slic3r::Polyline->new($points); + my $serialized = $polyline->serialize; + my $deserialized = $serialized->deserialize; + is scalar(@$deserialized), scalar(@$points), 'number of deserialized points'; + is_deeply $deserialized, $points, 'deserialized points coordinates'; +} + +#========================================================== + +__END__