Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Perimeter.pm « Slic3r « lib - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 286be429123e58db2e0b3483a8ffe71900cd4391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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 = $Slic3r::flow_width / $Slic3r::resolution;
        }
        
        # create one more offset to be used as boundary for fill
        {
            $distance -= scale $Slic3r::flow_width * $Slic3r::perimeter_infill_overlap_ratio;
            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;