Browse Source

Memory optimization and code cleanup. Don't keep deserialized paths

Alessandro Ranellucci 12 years ago
parent
commit
1697cb24a6

+ 30 - 11
lib/Slic3r/ExtrusionLoop.pm

@@ -13,15 +13,24 @@ has 'flow_spacing' => (is => 'rw');
 # see EXTR_ROLE_* constants in ExtrusionPath.pm
 # see EXTR_ROLE_* constants in ExtrusionPath.pm
 has 'role'         => (is => 'rw', required => 1);
 has 'role'         => (is => 'rw', required => 1);
 
 
-sub BUILD {
-    my $self = shift;
-    bless $self->polygon, 'Slic3r::Polygon';
-    $self->polygon($self->polygon->serialize);
-}
+use constant PACK_FMT => 'fca*';
 
 
-sub deserialize {
+# class or object method
+sub pack {
     my $self = shift;
     my $self = shift;
-    $self->polygon($self->polygon->deserialize);
+    my %args = @_;
+    
+    if (ref $self) {
+        %args = map { $_ => $self->$_ } qw(flow_spacing role polygon);
+    }
+    
+    my $o = \ pack PACK_FMT,
+        $args{flow_spacing} || -1,
+        $args{role}         // (die "Missing mandatory attribute 'role'"), #/
+        $args{polygon}->serialize;
+    
+    bless $o, 'Slic3r::ExtrusionLoop::Packed';
+    return $o;
 }
 }
 
 
 sub shortest_path {
 sub shortest_path {
@@ -33,8 +42,6 @@ sub split_at_index {
     my $self = shift;
     my $self = shift;
     my ($index) = @_;
     my ($index) = @_;
 
 
-    $self->deserialize;
-
     my @new_points = ();
     my @new_points = ();
     push @new_points, @{$self->polygon}[$index .. $#{$self->polygon}];
     push @new_points, @{$self->polygon}[$index .. $#{$self->polygon}];
     push @new_points, @{$self->polygon}[0 .. $index];
     push @new_points, @{$self->polygon}[0 .. $index];
@@ -52,8 +59,6 @@ sub split_at {
     
     
     $point = Slic3r::Point->new($point);
     $point = Slic3r::Point->new($point);
     
     
-    $self->deserialize;
-    
     # find index of point
     # find index of point
     my $i = -1;
     my $i = -1;
     for (my $n = 0; $n <= $#{$self->polygon}; $n++) {
     for (my $n = 0; $n <= $#{$self->polygon}; $n++) {
@@ -86,4 +91,18 @@ sub points {
     return $self->polygon;
     return $self->polygon;
 }
 }
 
 
+package Slic3r::ExtrusionLoop::Packed;
+sub unpack {
+    my $self = shift;
+    
+    my ($flow_spacing, $role, $polygon_s)
+        = unpack Slic3r::ExtrusionLoop::PACK_FMT, $$self;
+    
+    return Slic3r::ExtrusionLoop->new(
+        flow_spacing    => ($flow_spacing == -1) ? undef : $flow_spacing,
+        role            => $role,
+        polygon         => Slic3r::Polygon->deserialize($polygon_s),
+    );
+}
+
 1;
 1;

+ 37 - 12
lib/Slic3r/ExtrusionPath.pm

@@ -18,13 +18,11 @@ has 'polyline' => (
     handles     => [qw(merge_continuous_lines lines length reverse)],
     handles     => [qw(merge_continuous_lines lines length reverse)],
 );
 );
 
 
-# this integer represents the vertical thickness of the extrusion
-# expressed in layers
+# depth_layers is the vertical thickness of the extrusion expressed in layers
 has 'depth_layers' => (is => 'ro', default => sub {1});
 has 'depth_layers' => (is => 'ro', default => sub {1});
-
 has 'flow_spacing' => (is => 'rw');
 has 'flow_spacing' => (is => 'rw');
-
 has 'role'         => (is => 'rw', required => 1);
 has 'role'         => (is => 'rw', required => 1);
+
 use constant EXTR_ROLE_PERIMETER                    => 0;
 use constant EXTR_ROLE_PERIMETER                    => 0;
 use constant EXTR_ROLE_SMALLPERIMETER               => 1;
 use constant EXTR_ROLE_SMALLPERIMETER               => 1;
 use constant EXTR_ROLE_EXTERNAL_PERIMETER           => 2;
 use constant EXTR_ROLE_EXTERNAL_PERIMETER           => 2;
@@ -36,17 +34,30 @@ use constant EXTR_ROLE_BRIDGE                       => 7;
 use constant EXTR_ROLE_SKIRT                        => 8;
 use constant EXTR_ROLE_SKIRT                        => 8;
 use constant EXTR_ROLE_SUPPORTMATERIAL              => 9;
 use constant EXTR_ROLE_SUPPORTMATERIAL              => 9;
 
 
-sub BUILD {
-    my $self = shift;
-    bless $self->polyline, 'Slic3r::Polyline';
-    $self->polyline($self->polyline->serialize);
-}
+use constant PACK_FMT => 'cfca*';
 
 
-sub deserialize {
+# class or object method
+sub pack {
     my $self = shift;
     my $self = shift;
-    $self->polyline($self->polyline->deserialize);
+    my %args = @_;
+    
+    if (ref $self) {
+        %args = map { $_ => $self->$_ } qw(depth_layers flow_spacing role polyline);
+    }
+    
+    my $o = \ pack PACK_FMT,
+        $args{depth_layers} || 1,
+        $args{flow_spacing} || -1,
+        $args{role}         // (die "Missing mandatory attribute 'role'"), #/
+        $args{polyline}->serialize;
+    
+    bless $o, 'Slic3r::ExtrusionPath::Packed';
+    return $o;
 }
 }
 
 
+# no-op, this allows to use both packed and non-packed objects in Collections
+sub unpack { $_[0] }
+
 sub shortest_path {
 sub shortest_path {
     my $self = shift;
     my $self = shift;
     return $self;
     return $self;
@@ -152,7 +163,6 @@ sub detect_arcs {
     my $self = shift;
     my $self = shift;
     my ($max_angle, $len_epsilon) = @_;
     my ($max_angle, $len_epsilon) = @_;
     
     
-    $self->deserialize;
     $max_angle = deg2rad($max_angle || 15);
     $max_angle = deg2rad($max_angle || 15);
     $len_epsilon ||= 10 / $Slic3r::scaling_factor;
     $len_epsilon ||= 10 / $Slic3r::scaling_factor;
     
     
@@ -265,4 +275,19 @@ sub detect_arcs {
     return @paths;
     return @paths;
 }
 }
 
 
+package Slic3r::ExtrusionPath::Packed;
+sub unpack {
+    my $self = shift;
+    
+    my ($depth_layers, $flow_spacing, $role, $polyline_s)
+        = unpack Slic3r::ExtrusionPath::PACK_FMT, $$self;
+    
+    return Slic3r::ExtrusionPath->new(
+        depth_layers    => $depth_layers,
+        flow_spacing    => ($flow_spacing == -1) ? undef : $flow_spacing,
+        role            => $role,
+        polyline        => Slic3r::Polyline->deserialize($polyline_s),
+    );
+}
+
 1;
 1;

+ 3 - 15
lib/Slic3r/ExtrusionPath/Collection.pm

@@ -1,19 +1,7 @@
 package Slic3r::ExtrusionPath::Collection;
 package Slic3r::ExtrusionPath::Collection;
 use Moo;
 use Moo;
 
 
-
-has 'paths' => (
-    is      => 'rw',
-    #isa     => 'ArrayRef[Slic3r::ExtrusionPath]',
-    default => sub { [] },
-);
-
-sub add {
-    my $self = shift;
-    my ($path) = @_;
-    
-    push @{$self->paths}, $path;
-}
+has 'paths' => (is => 'rw', default => sub { [] });
 
 
 sub endpoints {
 sub endpoints {
     my $self = shift;
     my $self = shift;
@@ -24,8 +12,8 @@ sub shortest_path {
     my $self = shift;
     my $self = shift;
     my ($start_near) = @_;
     my ($start_near) = @_;
     
     
-    my @my_paths = @{$self->paths};
-    $_->deserialize for @my_paths;
+    my @my_paths = map $_->unpack, @{$self->paths};
+    
     my @paths = ();
     my @paths = ();
     my $start_at;
     my $start_at;
     my $endpoints = [ map $_->endpoints, @my_paths ];
     my $endpoints = [ map $_->endpoints, @my_paths ];

+ 3 - 3
lib/Slic3r/Fill.pm

@@ -162,7 +162,7 @@ sub make_fill {
         next unless @paths;
         next unless @paths;
         push @fills, Slic3r::ExtrusionPath::Collection->new(
         push @fills, Slic3r::ExtrusionPath::Collection->new(
             paths => [
             paths => [
-                map Slic3r::ExtrusionPath->new(
+                map Slic3r::ExtrusionPath->pack(
                     polyline => Slic3r::Polyline->new(@$_),
                     polyline => Slic3r::Polyline->new(@$_),
                     role => ($is_bridge
                     role => ($is_bridge
                         ? EXTR_ROLE_BRIDGE
                         ? EXTR_ROLE_BRIDGE
@@ -185,8 +185,8 @@ sub make_fill {
         );
         );
         push @fills, map {
         push @fills, map {
             $_->isa('Slic3r::Polygon')
             $_->isa('Slic3r::Polygon')
-                ? Slic3r::ExtrusionLoop->new(polygon  => $_, %args)->split_at_first_point
-                : Slic3r::ExtrusionPath->new(polyline => $_, %args),
+                ? Slic3r::ExtrusionLoop->pack(polygon  => $_, %args)->split_at_first_point
+                : Slic3r::ExtrusionPath->pack(polyline => $_, %args),
         } @{$layer->thin_fills};
         } @{$layer->thin_fills};
     }
     }
     push @fills_ordering_points, map $_->[0], @{$layer->thin_fills};
     push @fills_ordering_points, map $_->[0], @{$layer->thin_fills};

+ 0 - 2
lib/Slic3r/Fill/Concentric.pm

@@ -53,7 +53,6 @@ sub fill_surface {
     );
     );
     foreach my $loop (map Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_FILL), @loops) {
     foreach my $loop (map Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_FILL), @loops) {
         # extrude all loops ccw
         # extrude all loops ccw
-        $loop->deserialize;
         $loop->polygon->make_counter_clockwise;
         $loop->polygon->make_counter_clockwise;
         
         
         # find the point of the loop that is closest to the current extruder position
         # find the point of the loop that is closest to the current extruder position
@@ -62,7 +61,6 @@ sub fill_surface {
         
         
         # split the loop at the starting point and make a path
         # split the loop at the starting point and make a path
         my $path = $loop->split_at_index($index);
         my $path = $loop->split_at_index($index);
-        $path->deserialize;
         
         
         # clip the path to avoid the extruder to get exactly on the first point of the loop
         # clip the path to avoid the extruder to get exactly on the first point of the loop
         $path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15);
         $path->clip_end(scale($self->layer ? $self->layer->flow->width : $Slic3r::flow->width) * 0.15);

+ 1 - 1
lib/Slic3r/Fill/Honeycomb.pm

@@ -88,7 +88,7 @@ sub fill_surface {
         [ map @$_, $expolygon->offset_ex($overlap_distance) ],
         [ map @$_, $expolygon->offset_ex($overlap_distance) ],
     )};
     )};
     my $collection = Slic3r::ExtrusionPath::Collection->new(
     my $collection = Slic3r::ExtrusionPath::Collection->new(
-        paths => [ map Slic3r::ExtrusionPath->new(polyline => $_, role => -1), @paths ],
+        paths => [ map Slic3r::ExtrusionPath->pack(polyline => $_, role => -1), @paths ],
     );
     );
     
     
     return {}, map $_->polyline, $collection->shortest_path;
     return {}, map $_->polyline, $collection->shortest_path;

+ 5 - 9
lib/Slic3r/GCode.pm

@@ -79,12 +79,9 @@ sub change_layer {
 sub extrude {
 sub extrude {
     my $self = shift;
     my $self = shift;
     
     
-    if ($_[0]->isa('Slic3r::ExtrusionLoop')) {
-        $self->extrude_loop(@_);
-    } else {
-        $_[0]->deserialize;
-        $self->extrude_path(@_);
-    }
+    $_[0]->isa('Slic3r::ExtrusionLoop::Packed')
+        ? $self->extrude_loop(@_)
+        : $self->extrude_path(@_);
 }
 }
 
 
 sub extrude_loop {
 sub extrude_loop {
@@ -92,7 +89,7 @@ sub extrude_loop {
     my ($loop, $description) = @_;
     my ($loop, $description) = @_;
     
     
     # extrude all loops ccw
     # extrude all loops ccw
-    $loop->deserialize;
+    $loop = $loop->unpack;
     $loop->polygon->make_counter_clockwise;
     $loop->polygon->make_counter_clockwise;
     
     
     # find the point of the loop that is closest to the current extruder position
     # find the point of the loop that is closest to the current extruder position
@@ -107,7 +104,6 @@ sub extrude_loop {
     
     
     # split the loop at the starting point and make a path
     # split the loop at the starting point and make a path
     my $extrusion_path = $loop->split_at_index($start_index);
     my $extrusion_path = $loop->split_at_index($start_index);
-    $extrusion_path->deserialize;
     
     
     # clip the path to avoid the extruder to get exactly on the first point of the loop;
     # 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
     # if polyline was shorter than the clipping distance we'd get a null polyline, so
@@ -123,13 +119,13 @@ sub extrude_path {
     my $self = shift;
     my $self = shift;
     my ($path, $description, $recursive) = @_;
     my ($path, $description, $recursive) = @_;
     
     
+    $path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
     $path->merge_continuous_lines;
     $path->merge_continuous_lines;
     
     
     # detect arcs
     # detect arcs
     if ($Slic3r::gcode_arcs && !$recursive) {
     if ($Slic3r::gcode_arcs && !$recursive) {
         my $gcode = "";
         my $gcode = "";
         foreach my $arc_path ($path->detect_arcs) {
         foreach my $arc_path ($path->detect_arcs) {
-            $arc_path->deserialize;
             $gcode .= $self->extrude_path($arc_path, $description, 1);
             $gcode .= $self->extrude_path($arc_path, $description, 1);
         }
         }
         return $gcode;
         return $gcode;

+ 3 - 3
lib/Slic3r/Layer.pm

@@ -351,9 +351,9 @@ sub make_perimeters {
         my @thin_paths = ();
         my @thin_paths = ();
         for (@{ $self->thin_walls }) {
         for (@{ $self->thin_walls }) {
             if ($_->isa('Slic3r::Polygon')) {
             if ($_->isa('Slic3r::Polygon')) {
-                push @thin_paths, Slic3r::ExtrusionLoop->new(polygon => $_, role => EXTR_ROLE_PERIMETER);
+                push @thin_paths, Slic3r::ExtrusionLoop->pack(polygon => $_, role => EXTR_ROLE_PERIMETER);
             } else {
             } else {
-                push @thin_paths, Slic3r::ExtrusionPath->new(polyline => $_, role => EXTR_ROLE_PERIMETER);
+                push @thin_paths, Slic3r::ExtrusionPath->pack(polyline => $_, role => EXTR_ROLE_PERIMETER);
             }
             }
             $thin_paths[-1]->flow_spacing($self->perimeters_flow->spacing);
             $thin_paths[-1]->flow_spacing($self->perimeters_flow->spacing);
         }
         }
@@ -367,7 +367,7 @@ sub add_perimeter {
     my ($polygon, $role) = @_;
     my ($polygon, $role) = @_;
     
     
     return unless $polygon->is_printable($self->perimeters_flow->width);
     return unless $polygon->is_printable($self->perimeters_flow->width);
-    push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(
+    push @{ $self->perimeters }, Slic3r::ExtrusionLoop->pack(
         polygon         => $polygon,
         polygon         => $polygon,
         role            => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER),  #/
         role            => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER),  #/
         flow_spacing    => $self->perimeters_flow->spacing,
         flow_spacing    => $self->perimeters_flow->spacing,

+ 11 - 10
lib/Slic3r/Polyline.pm

@@ -17,7 +17,7 @@ sub new {
         $self = [ @_ ];
         $self = [ @_ ];
     }
     }
     
     
-    bless $self, $class;
+    bless $self, $class;use XXX; ZZZ $self if !defined $self->[0];
     bless $_, 'Slic3r::Point' for @$self;
     bless $_, 'Slic3r::Point' for @$self;
     $self;
     $self;
 }
 }
@@ -29,19 +29,20 @@ sub clone {
 
 
 sub serialize {
 sub serialize {
     my $self = shift;
     my $self = shift;
-    my $s = \ pack 'l*', map @$_, @$self;
-    bless $s, ref $self;
-    return $s;
+    return pack 'l*', map @$_, @$self;
 }
 }
 
 
 sub deserialize {
 sub deserialize {
+    my $class = shift;
+    my ($s) = @_;
+    
+    my @v = unpack '(l2)*', $s;
+    return $class->new(map [ $v[2*$_], $v[2*$_+1] ], 0 .. int($#v/2));
+}
+
+sub is_serialized {
     my $self = shift;
     my $self = shift;
-    return $self if reftype $self ne 'SCALAR';
-    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;
+    return (reftype $self) eq 'SCALAR' ? 1 : 0;
 }
 }
 
 
 sub id {
 sub id {

+ 3 - 3
lib/Slic3r/Print.pm

@@ -436,7 +436,7 @@ sub make_skirt {
         my @layer_points = (
         my @layer_points = (
             (map @$_, map @{$_->expolygon}, map @{$_->slices}, @layers),
             (map @$_, map @{$_->expolygon}, map @{$_->slices}, @layers),
             (map @$_, map @{$_->thin_walls}, @layers),
             (map @$_, map @{$_->thin_walls}, @layers),
-            (map @{$_->polyline->deserialize}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers),
+            (map @{$_->unpack->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers),
         );
         );
         push @points, map move_points($_, @layer_points), @{$self->copies->[$obj_idx]};
         push @points, map move_points($_, @layer_points), @{$self->copies->[$obj_idx]};
     }
     }
@@ -451,7 +451,7 @@ sub make_skirt {
     for (my $i = $Slic3r::skirts; $i > 0; $i--) {
     for (my $i = $Slic3r::skirts; $i > 0; $i--) {
         my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i));
         my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i));
         my $outline = offset([$convex_hull], $distance, $Slic3r::scaling_factor * 100, JT_ROUND);
         my $outline = offset([$convex_hull], $distance, $Slic3r::scaling_factor * 100, JT_ROUND);
-        push @skirt, Slic3r::ExtrusionLoop->new(
+        push @skirt, Slic3r::ExtrusionLoop->pack(
             polygon => Slic3r::Polygon->new(@{$outline->[0]}),
             polygon => Slic3r::Polygon->new(@{$outline->[0]}),
             role => EXTR_ROLE_SKIRT,
             role => EXTR_ROLE_SKIRT,
         );
         );
@@ -474,7 +474,7 @@ sub make_brim {
     my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
     my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
     my $num_loops = sprintf "%.0f", $Slic3r::brim_width / $flow->width;
     my $num_loops = sprintf "%.0f", $Slic3r::brim_width / $flow->width;
     for my $i (reverse 1 .. $num_loops) {
     for my $i (reverse 1 .. $num_loops) {
-        push @{$self->brim}, Slic3r::ExtrusionLoop->new(
+        push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
             polygon => Slic3r::Polygon->new($_),
             polygon => Slic3r::Polygon->new($_),
             role    => EXTR_ROLE_SKIRT,
             role    => EXTR_ROLE_SKIRT,
         ) for @{Math::Clipper::offset(\@islands, $i * scale $flow->spacing)};
         ) for @{Math::Clipper::offset(\@islands, $i * scale $flow->spacing)};

Some files were not shown because too many files changed in this diff