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

This commit is contained in:
Alessandro Ranellucci 2012-07-20 14:39:07 +02:00
parent 52fb02f29d
commit 1697cb24a6
11 changed files with 99 additions and 71 deletions

View File

@ -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 { use constant PACK_FMT => 'fca*';
my $self = shift;
bless $self->polygon, 'Slic3r::Polygon';
$self->polygon($self->polygon->serialize);
}
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;

View File

@ -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 # depth_layers is the vertical thickness of the extrusion expressed in layers
# 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,16 +34,29 @@ 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 { use constant PACK_FMT => 'cfca*';
# class or object method
sub pack {
my $self = shift; my $self = shift;
bless $self->polyline, 'Slic3r::Polyline'; my %args = @_;
$self->polyline($self->polyline->serialize);
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;
} }
sub deserialize { # no-op, this allows to use both packed and non-packed objects in Collections
my $self = shift; sub unpack { $_[0] }
$self->polyline($self->polyline->deserialize);
}
sub shortest_path { sub shortest_path {
my $self = shift; my $self = shift;
@ -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;

View File

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

View File

@ -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::ExtrusionLoop->pack(polygon => $_, %args)->split_at_first_point
: Slic3r::ExtrusionPath->new(polyline => $_, %args), : 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};

View File

@ -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);

View File

@ -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;

View File

@ -79,12 +79,9 @@ sub change_layer {
sub extrude { sub extrude {
my $self = shift; my $self = shift;
if ($_[0]->isa('Slic3r::ExtrusionLoop')) { $_[0]->isa('Slic3r::ExtrusionLoop::Packed')
$self->extrude_loop(@_); ? $self->extrude_loop(@_)
} else { : $self->extrude_path(@_);
$_[0]->deserialize;
$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;

View File

@ -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,

View File

@ -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; return pack 'l*', map @$_, @$self;
bless $s, ref $self;
return $s;
} }
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'; return (reftype $self) eq 'SCALAR' ? 1 : 0;
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 { sub id {

View File

@ -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)};

View File

@ -560,7 +560,6 @@ sub generate_support_material {
flow_spacing => $params->{flow_spacing}, flow_spacing => $params->{flow_spacing},
), @paths; ), @paths;
} }
$_->deserialize for @patterns;
push @$support_patterns, [@patterns]; push @$support_patterns, [@patterns];
} }
@ -580,7 +579,9 @@ sub generate_support_material {
my ($layer_id, $expolygons) = @_; my ($layer_id, $expolygons) = @_;
my @paths = (); my @paths = ();
foreach my $expolygon (@$expolygons) { foreach my $expolygon (@$expolygons) {
push @paths, map { $_->deserialize; $_->clip_with_expolygon($expolygon) } push @paths,
map $_->pack,
map $_->clip_with_expolygon($expolygon),
map $_->clip_with_polygon($expolygon->bounding_box_polygon), map $_->clip_with_polygon($expolygon->bounding_box_polygon),
@{$support_patterns->[ $layer_id % @$support_patterns ]}; @{$support_patterns->[ $layer_id % @$support_patterns ]};
}; };