diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index ac79c8d0..c97684f0 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -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; diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 6e9b76b3..717e1ad6 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -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; diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index e614fb1e..560b63a8 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -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 ]; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index b624e8aa..184ecad1 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -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}; diff --git a/lib/Slic3r/Fill/Concentric.pm b/lib/Slic3r/Fill/Concentric.pm index 71c19db4..94866e2a 100644 --- a/lib/Slic3r/Fill/Concentric.pm +++ b/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) { # 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); diff --git a/lib/Slic3r/Fill/Honeycomb.pm b/lib/Slic3r/Fill/Honeycomb.pm index 81a86b0d..cbc4f61d 100644 --- a/lib/Slic3r/Fill/Honeycomb.pm +++ b/lib/Slic3r/Fill/Honeycomb.pm @@ -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; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 69f5d628..0a7a1134 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -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; diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index e0a7b296..a95570d6 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -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, diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index e7c2c61c..33aba11b 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -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 { diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 6e9cc558..22e9002e 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -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)}; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 423455a8..f94e4867 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -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 ]}; };