mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	Memory optimization and code cleanup. Don't keep deserialized paths
This commit is contained in:
		
							parent
							
								
									52fb02f29d
								
							
						
					
					
						commit
						1697cb24a6
					
				
					 11 changed files with 99 additions and 71 deletions
				
			
		|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 ]; | ||||
|  |  | |||
|  | @ -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}; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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)}; | ||||
|  |  | |||
|  | @ -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 ]}; | ||||
|             }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci