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
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;
$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 {
@ -33,8 +42,6 @@ sub split_at_index {
my $self = shift;
my ($index) = @_;
$self->deserialize;
my @new_points = ();
push @new_points, @{$self->polygon}[$index .. $#{$self->polygon}];
push @new_points, @{$self->polygon}[0 .. $index];
@ -52,8 +59,6 @@ sub split_at {
$point = Slic3r::Point->new($point);
$self->deserialize;
# find index of point
my $i = -1;
for (my $n = 0; $n <= $#{$self->polygon}; $n++) {
@ -86,4 +91,18 @@ sub points {
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;

View File

@ -18,13 +18,11 @@ has 'polyline' => (
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 'flow_spacing' => (is => 'rw');
has 'role' => (is => 'rw', required => 1);
use constant EXTR_ROLE_PERIMETER => 0;
use constant EXTR_ROLE_SMALLPERIMETER => 1;
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_SUPPORTMATERIAL => 9;
sub BUILD {
use constant PACK_FMT => 'cfca*';
# class or object method
sub pack {
my $self = shift;
bless $self->polyline, 'Slic3r::Polyline';
$self->polyline($self->polyline->serialize);
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;
}
sub deserialize {
my $self = shift;
$self->polyline($self->polyline->deserialize);
}
# no-op, this allows to use both packed and non-packed objects in Collections
sub unpack { $_[0] }
sub shortest_path {
my $self = shift;
@ -152,7 +163,6 @@ sub detect_arcs {
my $self = shift;
my ($max_angle, $len_epsilon) = @_;
$self->deserialize;
$max_angle = deg2rad($max_angle || 15);
$len_epsilon ||= 10 / $Slic3r::scaling_factor;
@ -265,4 +275,19 @@ sub detect_arcs {
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;

View File

@ -1,19 +1,7 @@
package Slic3r::ExtrusionPath::Collection;
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 {
my $self = shift;
@ -24,8 +12,8 @@ sub shortest_path {
my $self = shift;
my ($start_near) = @_;
my @my_paths = @{$self->paths};
$_->deserialize for @my_paths;
my @my_paths = map $_->unpack, @{$self->paths};
my @paths = ();
my $start_at;
my $endpoints = [ map $_->endpoints, @my_paths ];

View File

@ -162,7 +162,7 @@ sub make_fill {
next unless @paths;
push @fills, Slic3r::ExtrusionPath::Collection->new(
paths => [
map Slic3r::ExtrusionPath->new(
map Slic3r::ExtrusionPath->pack(
polyline => Slic3r::Polyline->new(@$_),
role => ($is_bridge
? EXTR_ROLE_BRIDGE
@ -185,8 +185,8 @@ sub make_fill {
);
push @fills, map {
$_->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};
}
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) {
# 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
@ -62,7 +61,6 @@ sub fill_surface {
# split the loop at the starting point and make a path
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
$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) ],
)};
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;

View File

@ -79,12 +79,9 @@ sub change_layer {
sub extrude {
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 {
@ -92,7 +89,7 @@ sub extrude_loop {
my ($loop, $description) = @_;
# extrude all loops ccw
$loop->deserialize;
$loop = $loop->unpack;
$loop->polygon->make_counter_clockwise;
# 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
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;
# 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 ($path, $description, $recursive) = @_;
$path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
$path->merge_continuous_lines;
# detect arcs
if ($Slic3r::gcode_arcs && !$recursive) {
my $gcode = "";
foreach my $arc_path ($path->detect_arcs) {
$arc_path->deserialize;
$gcode .= $self->extrude_path($arc_path, $description, 1);
}
return $gcode;

View File

@ -351,9 +351,9 @@ sub make_perimeters {
my @thin_paths = ();
for (@{ $self->thin_walls }) {
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 {
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);
}
@ -367,7 +367,7 @@ sub add_perimeter {
my ($polygon, $role) = @_;
return unless $polygon->is_printable($self->perimeters_flow->width);
push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(
push @{ $self->perimeters }, Slic3r::ExtrusionLoop->pack(
polygon => $polygon,
role => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : ($role // EXTR_ROLE_PERIMETER), #/
flow_spacing => $self->perimeters_flow->spacing,

View File

@ -17,7 +17,7 @@ sub new {
$self = [ @_ ];
}
bless $self, $class;
bless $self, $class;use XXX; ZZZ $self if !defined $self->[0];
bless $_, 'Slic3r::Point' for @$self;
$self;
}
@ -29,19 +29,20 @@ sub clone {
sub serialize {
my $self = shift;
my $s = \ pack 'l*', map @$_, @$self;
bless $s, ref $self;
return $s;
return pack 'l*', map @$_, @$self;
}
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;
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 {

View File

@ -436,7 +436,7 @@ sub make_skirt {
my @layer_points = (
(map @$_, map @{$_->expolygon}, map @{$_->slices}, @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]};
}
@ -451,7 +451,7 @@ sub make_skirt {
for (my $i = $Slic3r::skirts; $i > 0; $i--) {
my $distance = scale ($Slic3r::skirt_distance + ($flow->spacing * $i));
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]}),
role => EXTR_ROLE_SKIRT,
);
@ -474,7 +474,7 @@ sub make_brim {
my $flow = $Slic3r::first_layer_flow || $Slic3r::flow;
my $num_loops = sprintf "%.0f", $Slic3r::brim_width / $flow->width;
for my $i (reverse 1 .. $num_loops) {
push @{$self->brim}, Slic3r::ExtrusionLoop->new(
push @{$self->brim}, Slic3r::ExtrusionLoop->pack(
polygon => Slic3r::Polygon->new($_),
role => EXTR_ROLE_SKIRT,
) for @{Math::Clipper::offset(\@islands, $i * scale $flow->spacing)};

View File

@ -560,7 +560,6 @@ sub generate_support_material {
flow_spacing => $params->{flow_spacing},
), @paths;
}
$_->deserialize for @patterns;
push @$support_patterns, [@patterns];
}
@ -580,7 +579,9 @@ sub generate_support_material {
my ($layer_id, $expolygons) = @_;
my @paths = ();
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),
@{$support_patterns->[ $layer_id % @$support_patterns ]};
};