mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Massive reduction of memory usage (down to one third).
This commit is contained in:
		
							parent
							
								
									882a022e3a
								
							
						
					
					
						commit
						b246480535
					
				
					 10 changed files with 75 additions and 31 deletions
				
			
		|  | @ -80,7 +80,7 @@ our $perimeter_acceleration = 25;   # mm/s^2 | ||||||
| our $infill_acceleration    = 50;   # mm/s^2 | our $infill_acceleration    = 50;   # mm/s^2 | ||||||
| 
 | 
 | ||||||
| # accuracy options | # accuracy options | ||||||
| our $scaling_factor         = 0.00000001; | our $scaling_factor         = 0.000001; | ||||||
| our $resolution             = 0.01; | our $resolution             = 0.01; | ||||||
| our $small_perimeter_length = (6.5 / $scaling_factor)*2*PI; | our $small_perimeter_length = (6.5 / $scaling_factor)*2*PI; | ||||||
| our $layer_height           = 0.4; | our $layer_height           = 0.4; | ||||||
|  |  | ||||||
|  | @ -78,6 +78,7 @@ sub extrude_loop { | ||||||
|     my ($loop, $description) = @_; |     my ($loop, $description) = @_; | ||||||
|      |      | ||||||
|     # 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 | ||||||
|  | @ -85,6 +86,7 @@ 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($start_at); |     my $extrusion_path = $loop->split_at($start_at); | ||||||
|  |     $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 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ use Moo; | ||||||
| 
 | 
 | ||||||
| # the underlying Slic3r::Polygon objects holds the geometry | # the underlying Slic3r::Polygon objects holds the geometry | ||||||
| has 'polygon' => ( | has 'polygon' => ( | ||||||
|     is          => 'ro', |     is          => 'rw', | ||||||
|     required    => 1, |     required    => 1, | ||||||
|     handles     => [qw(is_printable nearest_point_to)], |     handles     => [qw(is_printable nearest_point_to)], | ||||||
| ); | ); | ||||||
|  | @ -14,6 +14,12 @@ has 'role'         => (is => 'rw', required => 1); | ||||||
| sub BUILD { | sub BUILD { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     bless $self->polygon, 'Slic3r::Polygon'; |     bless $self->polygon, 'Slic3r::Polygon'; | ||||||
|  |     $self->polygon($self->polygon->serialize); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub deserialize { | ||||||
|  |     my $self = shift; | ||||||
|  |     $self->polygon($self->polygon->deserialize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub split_at { | sub split_at { | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points); | ||||||
| 
 | 
 | ||||||
| # the underlying Slic3r::Polyline objects holds the geometry | # the underlying Slic3r::Polyline objects holds the geometry | ||||||
| has 'polyline' => ( | has 'polyline' => ( | ||||||
|     is          => 'ro', |     is          => 'rw', | ||||||
|     required    => 1, |     required    => 1, | ||||||
|     handles     => [qw(merge_continuous_lines lines length)], |     handles     => [qw(merge_continuous_lines lines length)], | ||||||
| ); | ); | ||||||
|  | @ -34,6 +34,12 @@ use constant EXTR_ROLE_SUPPORTMATERIAL  => 6; | ||||||
| sub BUILD { | sub BUILD { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     bless $self->polyline, 'Slic3r::Polyline'; |     bless $self->polyline, 'Slic3r::Polyline'; | ||||||
|  |     $self->polyline($self->polyline->serialize); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub deserialize { | ||||||
|  |     my $self = shift; | ||||||
|  |     $self->polyline($self->polyline->deserialize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub clip_end { | sub clip_end { | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ sub shortest_path { | ||||||
|     my ($start_near) = @_; |     my ($start_near) = @_; | ||||||
|      |      | ||||||
|     my @my_paths = @{$self->paths}; |     my @my_paths = @{$self->paths}; | ||||||
|  |     $_->deserialize for @my_paths; | ||||||
|     my @paths = (); |     my @paths = (); | ||||||
|     my $start_at; |     my $start_at; | ||||||
|     CYCLE: while (@my_paths) { |     CYCLE: while (@my_paths) { | ||||||
|  |  | ||||||
|  | @ -236,7 +236,7 @@ sub polyline_lines { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub polygon_lines { | sub polygon_lines { | ||||||
|     my ($polygon) = @_; |     my ($polygon) = @_;use XXX; ZZZ $polygon if !eval { @$polygon }; | ||||||
|     return polyline_lines([ @$polygon, $polygon->[0] ]); |     return polyline_lines([ @$polygon, $polygon->[0] ]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -284,19 +284,14 @@ sub make_perimeters { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         foreach my $hole (reverse @holes) { |         # do holes, then contours starting from innermost one | ||||||
|             push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $hole, role => EXTR_ROLE_PERIMETER); |         foreach my $polygon ((reverse @holes), (map $_->contour, map @$_, reverse @$island)) { | ||||||
|  |             next unless $polygon->is_printable; | ||||||
|  |             push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new( | ||||||
|  |                 polygon => $polygon, | ||||||
|  |                 role => (abs($polygon->length) <= $Slic3r::small_perimeter_length) ? EXTR_ROLE_SMALLPERIMETER : EXTR_ROLE_PERIMETER, | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         # do contours starting from innermost one |  | ||||||
|         foreach my $contour (map $_->contour, map @$_, reverse @$island) { |  | ||||||
|             push @{ $self->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $contour, role => EXTR_ROLE_PERIMETER); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     # detect small perimeters by checking their area |  | ||||||
|     for (@{ $self->perimeters }) { |  | ||||||
|         $_->role(EXTR_ROLE_SMALLPERIMETER) if abs($_->polygon->length) <= $Slic3r::small_perimeter_length; |  | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     # add thin walls as perimeters |     # add thin walls as perimeters | ||||||
|  | @ -384,16 +379,6 @@ sub remove_small_surfaces { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub remove_small_perimeters { |  | ||||||
|     my $self = shift; |  | ||||||
|     my @good_perimeters = grep $_->is_printable, @{$self->perimeters}; |  | ||||||
|     Slic3r::debugf "removed %d unprintable perimeters at layer %d\n", |  | ||||||
|         (@{$self->perimeters} - @good_perimeters), $self->id |  | ||||||
|         if @good_perimeters != @{$self->perimeters}; |  | ||||||
|      |  | ||||||
|     @{$self->perimeters} = @good_perimeters; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| # make bridges printable | # make bridges printable | ||||||
| sub process_bridges { | sub process_bridges { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|  |  | ||||||
|  | @ -21,6 +21,22 @@ sub new { | ||||||
|     $self; |     $self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | sub serialize { | ||||||
|  |     my $self = shift; | ||||||
|  |     my $s = \ pack 'l*', map @$_, @$self; | ||||||
|  |     bless $s, ref $self; | ||||||
|  |     return $s; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub deserialize { | ||||||
|  |     my $self = shift; | ||||||
|  |     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 { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     return join ' - ', sort map $_->id, @$self; |     return join ' - ', sort map $_->id, @$self; | ||||||
|  |  | ||||||
|  | @ -188,11 +188,6 @@ sub export_gcode { | ||||||
|     $status_cb->(45, "Detect bridges"); |     $status_cb->(45, "Detect bridges"); | ||||||
|     $_->process_bridges for map @{$_->layers}, @{$self->objects}; |     $_->process_bridges for map @{$_->layers}, @{$self->objects}; | ||||||
|      |      | ||||||
|     # this will remove unprintable perimeter loops |  | ||||||
|     # (those that are too tight for extrusion) |  | ||||||
|     $status_cb->(50, "Cleaning up the perimeters"); |  | ||||||
|     $_->remove_small_perimeters for map @{$_->layers}, @{$self->objects}; |  | ||||||
|      |  | ||||||
|     # detect which fill surfaces are near external layers |     # detect which fill surfaces are near external layers | ||||||
|     # they will be split in internal and internal-solid surfaces |     # they will be split in internal and internal-solid surfaces | ||||||
|     $status_cb->(60, "Generating horizontal shells"); |     $status_cb->(60, "Generating horizontal shells"); | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								t/serialize.t
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								t/serialize.t
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | use Test::More; | ||||||
|  | use strict; | ||||||
|  | use warnings; | ||||||
|  | 
 | ||||||
|  | plan tests => 2; | ||||||
|  | 
 | ||||||
|  | BEGIN { | ||||||
|  |     use FindBin; | ||||||
|  |     use lib "$FindBin::Bin/../lib"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | use Slic3r; | ||||||
|  | use Slic3r::Geometry qw(scale); | ||||||
|  | 
 | ||||||
|  | #========================================================== | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  |     my $points = [ | ||||||
|  |         [226,701], [260,681], [109,420], [149,397], [300,658], [308,654], | ||||||
|  |     ]; | ||||||
|  |     foreach my $point (@$points) { | ||||||
|  |         @$point = map scale $_, @$point; | ||||||
|  |     } | ||||||
|  |     my $polyline = Slic3r::Polyline->new($points); | ||||||
|  |     my $serialized = $polyline->serialize; | ||||||
|  |     my $deserialized = $serialized->deserialize; | ||||||
|  |     is scalar(@$deserialized), scalar(@$points), 'number of deserialized points'; | ||||||
|  |     is_deeply $deserialized, $points, 'deserialized points coordinates'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #========================================================== | ||||||
|  | 
 | ||||||
|  | __END__ | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci