Browse Source

Merge branch 'master' into avoid-crossing-perimeters

Conflicts:
	README.markdown
	lib/Slic3r/ExPolygon.pm
	slic3r.pl
Alessandro Ranellucci 12 years ago
parent
commit
d061534b83

+ 3 - 0
README.markdown

@@ -171,6 +171,9 @@ The author of the Silk icon set is Mark James.
         --extra-perimeters  Add more perimeters when needed (default: yes)
         --randomize-start   Randomize starting point across layers (default: yes)
         --avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no)
+        --solid-infill-below-area
+                            Force solid infill when a region has a smaller area than this threshold
+                            (mm^2, default: 70)
       
        Support material options:
         --support-material  Generate support material for overhangs

+ 8 - 0
lib/Slic3r/Config.pm

@@ -449,6 +449,14 @@ our $Options = {
         max     => 359,
         default => 45,
     },
+    'solid_infill_below_area' => {
+        label   => 'Solid infill threshold area',
+        tooltip => 'Force solid infill for regions having a smaller area than the specified threshold.',
+        sidetext => 'mm²',
+        cli     => 'solid-infill-below-area=f',
+        type    => 'f',
+        default => 70,
+    },
     'extra_perimeters' => {
         label   => 'Generate extra perimeters when needed',
         cli     => 'extra-perimeters!',

+ 4 - 1
lib/Slic3r/Fill/Honeycomb.pm

@@ -83,7 +83,10 @@ sub fill_surface {
         $self->cache->{$cache_id} = [@polygons];
     }
     
-    my @paths = map Slic3r::Polyline->new(@$_, $_->[0]), map @$_, @{intersection_ex(
+    # build polylines from polygons without re-appending the initial point:
+    # this cuts the last segment on purpose, so that the jump to the next 
+    # path is more straight
+    my @paths = map Slic3r::Polyline->new(@$_), map @$_, @{intersection_ex(
         $self->cache->{$cache_id},
         [ map @$_, $expolygon->offset_ex($overlap_distance) ],
     )};

+ 6 - 4
lib/Slic3r/Fill/Rectilinear.pm

@@ -14,9 +14,8 @@ sub fill_surface {
     my $rotate_vector = $self->infill_direction($surface);
     $self->rotate_points($expolygon, $rotate_vector);
     
-    my ($expolygon_off) = $expolygon->offset_ex(scale 0.3);
+    my ($expolygon_off) = $expolygon->offset_ex(scale $params{flow_spacing}/2);
     return {} if !$expolygon_off;  # skip some very small polygons (which shouldn't arrive here)
-    my ($expolygon_epsilon_off) = $expolygon->offset_ex(scale epsilon);
     my $bounding_box = [ $expolygon->bounding_box ];
     
     my $min_spacing = scale $params{flow_spacing};
@@ -46,8 +45,11 @@ sub fill_surface {
         push @vertical_lines, $vertical_line;
         $x += $distance_between_lines;
     }
+    
+    # clip paths against a slightly offsetted expolygon, so that the first and last paths
+    # are kept even if the expolygon has vertical sides
     my @paths = @{ Boost::Geometry::Utils::polygon_linestring_intersection(
-        $expolygon_epsilon_off->boost_polygon,
+        +($expolygon->offset_ex(scale epsilon))[0]->boost_polygon,  # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object
         Boost::Geometry::Utils::linestring(@vertical_lines),
     ) };
     for (@paths) {
@@ -78,7 +80,7 @@ sub fill_surface {
                 # TODO: we should also check that both points are on a fill_boundary to avoid 
                 # connecting paths on the boundaries of internal regions
                 if ($can_connect->(@distance, $paths[-1][-1], $path->points->[0])
-                    && $expolygon_off->encloses_line(Slic3r::Line->new($paths[-1][-1], $path->points->[0]))) {
+                    && $expolygon_off->encloses_line(Slic3r::Line->new($paths[-1][-1], $path->points->[0]), $tolerance)) {
                     push @{$paths[-1]}, @{$path->points};
                     next;
                 }

+ 1 - 1
lib/Slic3r/GUI/Tab.pm

@@ -405,7 +405,7 @@ sub build {
         },
         {
             title => 'Advanced',
-            options => [qw(infill_every_layers fill_angle)],
+            options => [qw(infill_every_layers fill_angle solid_infill_below_area)],
         },
     ]);
     

+ 17 - 21
lib/Slic3r/Layer.pm

@@ -191,7 +191,6 @@ sub make_perimeters {
     # for each island:
     foreach my $surface (@surfaces) {
         my @last_offsets = ($surface->expolygon);
-        my $distance = 0;
         
         # experimental hole compensation (see ArcCompensation in the RepRap wiki)
         if (0) {
@@ -216,32 +215,29 @@ sub make_perimeters {
             }
         }
         
+        my $distance = scale $self->perimeter_flow->spacing;
         my @gaps = ();
         
-        # generate perimeters inwards
+        # generate perimeters inwards (loop 0 is the external one)
         my $loop_number = $Slic3r::Config->perimeters + ($surface->additional_inner_perimeters || 0);
-        push @perimeters, [];
-        for (my $loop = 0; $loop < $loop_number; $loop++) {
+        push @perimeters, [[@last_offsets]];
+        for (my $loop = 1; $loop < $loop_number; $loop++) {
             # offsetting a polygon can result in one or many offset polygons
-            if ($distance) {
-                my @new_offsets = ();
-                foreach my $expolygon (@last_offsets) {
-                    my @offsets = map $_->offset_ex(+0.5*$distance), $expolygon->offset_ex(-1.5*$distance);
-                    push @new_offsets, @offsets;
-                    
-                    my $diff = diff_ex(
-                        [ map @$_, $expolygon->offset_ex(-$distance) ],
-                        [ map @$_, @offsets ],
-                    );
-                    push @gaps, grep $_->area >= $gap_area_threshold, @$diff;
-                }
-                @last_offsets = @new_offsets;
+            my @new_offsets = ();
+            foreach my $expolygon (@last_offsets) {
+                my @offsets = map $_->offset_ex(+0.5*$distance), $expolygon->offset_ex(-1.5*$distance);
+                push @new_offsets, @offsets;
+                
+                my $diff = diff_ex(
+                    [ map @$_, $expolygon->offset_ex(-$distance) ],
+                    [ map @$_, @offsets ],
+                );
+                push @gaps, grep $_->area >= $gap_area_threshold, @$diff;
             }
+            @last_offsets = @new_offsets;
+            
             last if !@last_offsets;
             push @{ $perimeters[-1] }, [@last_offsets];
-            
-            # offset distance for inner loops
-            $distance = scale $self->perimeter_flow->spacing;
         }
         
         # create one more offset to be used as boundary for fill
@@ -365,7 +361,7 @@ sub prepare_fill_surfaces {
         
     # turn too small internal regions into solid regions
     {
-        my $min_area = ((7 * $self->infill_flow->spacing / &Slic3r::SCALING_FACTOR)**2) * PI;
+        my $min_area = scale scale $Slic3r::Config->solid_infill_below_area; # scaling an area requires two calls!
         my @small = grep $_->surface_type == S_TYPE_INTERNAL && $_->expolygon->contour->area <= $min_area, @surfaces;
         $_->surface_type(S_TYPE_INTERNALSOLID) for @small;
         Slic3r::debugf "identified %d small surfaces at layer %d\n", scalar(@small), $self->id if @small > 0;

+ 0 - 5
lib/Slic3r/Point.pm

@@ -32,11 +32,6 @@ sub cast {
     }
 }
 
-sub id {
-    my $self = shift;
-    return join ',', @$self;
-}
-
 sub coordinates {
     my $self = shift;
     return @$self;

+ 3 - 0
slic3r.pl

@@ -214,6 +214,9 @@ $j
     --extra-perimeters  Add more perimeters when needed (default: yes)
     --randomize-start   Randomize starting point across layers (default: yes)
     --avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no)
+    --solid-infill-below-area
+                        Force solid infill when a region has a smaller area than this threshold
+                        (mm^2, default: $config->{solid_infill_below_area})
   
    Support material options:
     --support-material  Generate support material for overhangs