mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			81 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| package Slic3r::Perimeter;
 | |
| use Moo;
 | |
| 
 | |
| use Math::Clipper ':all';
 | |
| use Slic3r::Geometry qw(X Y shortest_path scale);
 | |
| use XXX;
 | |
| 
 | |
| sub make_perimeter {
 | |
|     my $self = shift;
 | |
|     my ($layer) = @_;
 | |
|     printf "Making perimeter for layer %d\n", $layer->id;
 | |
|     
 | |
|     # at least one perimeter is required
 | |
|     die "Can't slice object with no perimeters!\n"
 | |
|         if $Slic3r::perimeters == 0;
 | |
|     
 | |
|     # this array will hold one arrayref per original surface;
 | |
|     # each item of this arrayref is an arrayref representing a depth (from inner
 | |
|     # perimeters to outer); each item of this arrayref is an ExPolygon:
 | |
|     # @perimeters = (
 | |
|     #    [ # first object (identified by a single surface before offsetting)
 | |
|     #        [ Slic3r::ExPolygon, Slic3r::ExPolygon... ],  #depth 0: outer loop
 | |
|     #        [ Slic3r::ExPolygon, Slic3r::ExPolygon... ],  #depth 1: inner loop
 | |
|     #    ],
 | |
|     #    [ # second object
 | |
|     #        ...
 | |
|     #    ]
 | |
|     # )
 | |
|     my @perimeters = ();  # one item per depth; each item
 | |
|     
 | |
|     # organize perimeter surfaces using a shortest path search
 | |
|     my @surfaces = @{shortest_path([
 | |
|         map [ $_->contour->points->[0], $_ ], @{$layer->slices},
 | |
|     ])};
 | |
|     
 | |
|     foreach my $surface (@surfaces) {
 | |
|         my @last_offsets = ($surface->expolygon);
 | |
|         my $distance = 0;
 | |
|         
 | |
|         # create other offsets
 | |
|         push @perimeters, [];
 | |
|         for (my $loop = 0; $loop < $Slic3r::perimeters; $loop++) {
 | |
|             # offsetting a polygon can result in one or many offset polygons
 | |
|             @last_offsets = map $_->offset_ex(-$distance), @last_offsets if $distance;
 | |
|             push @{ $perimeters[-1] }, [@last_offsets];
 | |
|             
 | |
|             # offset distance for inner loops
 | |
|             $distance = scale $Slic3r::flow_spacing;
 | |
|         }
 | |
|         
 | |
|         # create one more offset to be used as boundary for fill
 | |
|         {
 | |
|             $distance -= scale $Slic3r::flow_spacing;
 | |
|             my @fill_boundaries = map Slic3r::Surface->cast_from_expolygon
 | |
|                 ($_, surface_type => $surface->surface_type),
 | |
|                 map $_->offset_ex(-$distance), @last_offsets;
 | |
|             
 | |
|             push @{ $layer->fill_boundaries }, @fill_boundaries if @fill_boundaries;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     # process one island (original surface) at time
 | |
|     foreach my $island (@perimeters) {
 | |
|         # do holes starting from innermost one
 | |
|         foreach my $hole (map $_->holes, map @$_, @$island) {
 | |
|             push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($hole, role => 'perimeter');
 | |
|         }
 | |
|         
 | |
|         # do contours starting from innermost one
 | |
|         foreach my $contour (map $_->contour, map @$_, reverse @$island) {
 | |
|             push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($contour, role => 'perimeter');
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     # detect small perimeters by checking their area
 | |
|     for (@{ $layer->perimeters }) {
 | |
|         $_->role('small-perimeter') if $_->polygon->area < $Slic3r::small_perimeter_area;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 1;
 | 
