Browse Source

Merge branch 'master' into xsdata

Conflicts:
	lib/Slic3r.pm
	lib/Slic3r/ExPolygon.pm
	lib/Slic3r/Fill.pm
	lib/Slic3r/Fill/Rectilinear.pm
	lib/Slic3r/GCode.pm
	lib/Slic3r/GUI/Plater.pm
	lib/Slic3r/Geometry/Clipper.pm
	lib/Slic3r/Layer/Region.pm
	lib/Slic3r/Print.pm
	lib/Slic3r/Print/Object.pm
	lib/Slic3r/TriangleMesh.pm
	t/shells.t
	xs/MANIFEST
Alessandro Ranellucci 11 years ago
parent
commit
b38cc2c244
10 changed files with 114 additions and 75 deletions
  1. 1 0
      Build.PL
  2. 0 1
      MANIFEST
  3. 7 2
      README.markdown
  4. 4 0
      lib/Slic3r.pm
  5. 13 6
      lib/Slic3r/Config.pm
  6. 19 7
      lib/Slic3r/ExPolygon.pm
  7. 4 3
      lib/Slic3r/Fill.pm
  8. 41 47
      lib/Slic3r/Fill/Rectilinear.pm
  9. 1 1
      lib/Slic3r/Format/STL.pm
  10. 24 8
      lib/Slic3r/GCode.pm

+ 1 - 0
Build.PL

@@ -99,6 +99,7 @@ EOF
     # temporarily require this dev version until this upstream bug
     # is resolved: https://rt.cpan.org/Ticket/Display.html?id=86367
     system $cpanm, 'SMUELLER/ExtUtils-ParseXS-3.18_04.tar.gz';
+    system './xs/Build', 'distclean' if -e './xs/Build';
     system $cpanm, '--reinstall', './xs';
 }
 

+ 0 - 1
MANIFEST

@@ -88,7 +88,6 @@ t/support.t
 t/svg.t
 t/vibrationlimit.t
 utils/amf-to-stl.pl
-utils/file_info.pl
 utils/gcode_sectioncut.pl
 utils/post-processing/filament-weight.pl
 utils/post-processing/prowl-notification.pl

+ 7 - 2
README.markdown

@@ -80,7 +80,7 @@ The author of the Silk icon set is Mark James.
 
 ## How can I invoke slic3r.pl using the command line?
 
-    Usage: slic3r.pl [ OPTIONS ] file.stl
+    Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
     
         --help              Output this usage screen and exit
         --version           Output the version of Slic3r and exit
@@ -90,7 +90,10 @@ The author of the Silk icon set is Mark James.
         -o, --output <file> File to output gcode to (by default, the file will be saved
                             into the same directory as the input file using the 
                             --output-filename-format to generate the filename)
-        --repair            Automatically repair given STL files and saves them as _fixed.obj
+    
+      Non-slicing actions (no G-code will be generated):
+        --repair            Repair given STL files and save them as <name>_fixed.obj
+        --info              Output information about the supplied file(s) and exit
         
       GUI options:
         --no-plater         Disable the plater tab
@@ -322,6 +325,8 @@ The author of the Silk icon set is Mark James.
         --infill-extruder   Extruder to use for infill (1+, default: 1)
         --support-material-extruder
                             Extruder to use for support material (1+, default: 1)
+        --support-material-interface-extruder
+                            Extruder to use for support material interface (1+, default: 1)
 
 If you want to change a preset file, just do
 

+ 4 - 0
lib/Slic3r.pm

@@ -19,6 +19,10 @@ our $have_threads;
 BEGIN {
     use Config;
     $have_threads = $Config{useithreads} && eval "use threads; use threads::shared; use Thread::Queue; 1";
+    
+    ### temporarily disable threads if using the broken Moo version
+    use Moo;
+    $have_threads = 0 if $Moo::VERSION == 1.003000;
 }
 
 warn "Running Slic3r under Perl >= 5.16 is not supported nor recommended\n"

+ 13 - 6
lib/Slic3r/Config.pm

@@ -204,11 +204,18 @@ our $Options = {
     },
     'support_material_extruder' => {
         label   => 'Support material extruder',
-        tooltip => 'The extruder to use when printing support material. This affects brim too.',
+        tooltip => 'The extruder to use when printing support material. This affects brim and raft too.',
         cli     => 'support-material-extruder=i',
         type    => 'i',
         default => 1,
     },
+    'support_material_interface_extruder' => {
+        label   => 'Support material interface extruder',
+        tooltip => 'The extruder to use when printing support material interface. This affects raft too.',
+        cli     => 'support-material-interface-extruder=i',
+        type    => 'i',
+        default => 1,
+    },
     
     # filament options
     'first_layer_bed_temperature' => {
@@ -652,7 +659,7 @@ our $Options = {
         type    => 'select',
         values  => [qw(rectilinear rectilinear-grid honeycomb)],
         labels  => ['rectilinear', 'rectilinear grid', 'honeycomb'],
-        default => 'rectilinear',
+        default => 'honeycomb',
     },
     'support_material_spacing' => {
         label   => 'Pattern spacing',
@@ -676,7 +683,7 @@ our $Options = {
         sidetext => 'layers',
         cli     => 'support-material-interface-layers=i',
         type    => 'i',
-        default => 0,
+        default => 3,
     },
     'support_material_interface_spacing' => {
         label   => 'Interface pattern spacing',
@@ -696,7 +703,7 @@ our $Options = {
     },
     'raft_layers' => {
         label   => 'Raft layers',
-        tooltip => 'Number of total raft layers to insert below the object(s).',
+        tooltip => 'The object will be raised by this number of layers, and support material will be generated under it.',
         sidetext => 'layers',
         cli     => 'raft-layers=i',
         type    => 'i',
@@ -814,7 +821,7 @@ END
     },
     'retract_lift' => {
         label   => 'Lift Z',
-        tooltip => 'If you set this to a positive value, Z is quickly raised every time a retraction is triggered.',
+        tooltip => 'If you set this to a positive value, Z is quickly raised every time a retraction is triggered. When using multiple extruders, only the setting for the first extruder will be considered.',
         sidetext => 'mm',
         cli     => 'retract-lift=f@',
         type    => 'f',
@@ -832,7 +839,7 @@ END
         default => [1],
     },
     'wipe' => {
-        label   => 'Wipe before retract',
+        label   => 'Wipe while retracting',
         tooltip => 'This flag will move the nozzle while retracting to minimize the possible blob on leaky extruders.',
         cli     => 'wipe!',
         type    => 'bool',

+ 19 - 7
lib/Slic3r/ExPolygon.pm

@@ -44,6 +44,12 @@ sub wkt {
         join ',', map "($_)", map { join ',', map "$_->[0] $_->[1]", @$_ } @$self;
 }
 
+sub dump_perl {
+    my $self = shift;
+    return sprintf "[%s]", 
+        join ',', map "[$_]", map { join ',', map "[$_->[0],$_->[1]]", @$_ } @$self;
+}
+
 sub offset {
     my $self = shift;
     return Slic3r::Geometry::Clipper::offset(\@$self, @_);
@@ -108,15 +114,21 @@ sub clip_line {
     ];
 }
 
-sub simplify {
+sub simplify_as_polygons {
     my $self = shift;
     my ($tolerance) = @_;
     
     # it would be nice to have a multilinestring_simplify method in B::G::U
-    my @simplified = Slic3r::Geometry::Clipper::simplify_polygons(
+    return @{Slic3r::Geometry::Clipper::simplify_polygons(
         [ map Boost::Geometry::Utils::linestring_simplify($_, $tolerance), @{$self->pp} ],
-    );
-    return @{ Slic3r::Geometry::Clipper::union_ex([ @simplified ]) };
+    )};
+}
+
+sub simplify {
+    my $self = shift;
+    my ($tolerance) = @_;
+    
+    return @{ Slic3r::Geometry::Clipper::union_ex([ $self->simplify_as_polygons($tolerance) ]) };
 }
 
 sub area {
@@ -146,7 +158,7 @@ sub medial_axis {
         push @points, @$polygon;
     }
     
-    my $voronoi = Math::Geometry::Voronoi->new(points => \@points);
+    my $voronoi = Math::Geometry::Voronoi->new(points => [ map $_->pp, @points ]);
     $voronoi->compute;
     
     my @skeleton_lines = ();
@@ -158,8 +170,8 @@ sub medial_axis {
         next if $edge->[1] == -1 || $edge->[2] == -1;
         
         my ($a, $b);
-        $a = $vertices->[$edge->[1]];
-        $b = $vertices->[$edge->[2]];
+        $a = Slic3r::Point->new(@{$vertices->[$edge->[1]]});
+        $b = Slic3r::Point->new(@{$vertices->[$edge->[2]]});
         
         next if !$self->encloses_point_quick($a) || !$self->encloses_point_quick($b);
         

+ 4 - 3
lib/Slic3r/Fill.pm

@@ -162,7 +162,6 @@ sub make_fill {
             $surface,
             density         => $density,
             flow_spacing    => $flow_spacing,
-            dont_adjust     => $is_bridge,
         );
         next unless @polylines;
         
@@ -190,8 +189,10 @@ sub make_fill {
     }
     
     # add thin fill regions
-    push @fills, @{$layerm->thin_fills};
-    push @fills_ordering_points, map $_->[0], @{$layerm->thin_fills};
+    if (@{ $layerm->thin_fills }) {
+        push @fills, Slic3r::ExtrusionPath::Collection->new(@{$layerm->thin_fills});
+        push @fills_ordering_points, $fills[-1]->first_point;
+    }
     
     # organize infill paths using a nearest-neighbor search
     @fills = @fills[ chained_path(\@fills_ordering_points) ];

+ 41 - 47
lib/Slic3r/Fill/Rectilinear.pm

@@ -5,7 +5,7 @@ extends 'Slic3r::Fill::Base';
 
 has 'cache'         => (is => 'rw', default => sub {{}});
 
-use Slic3r::Geometry qw(A B X Y scale unscale scaled_epsilon);
+use Slic3r::Geometry qw(A B X Y MIN scale unscale scaled_epsilon);
 
 sub fill_surface {
     my $self = shift;
@@ -16,73 +16,67 @@ sub fill_surface {
     my $rotate_vector = $self->infill_direction($surface);
     $self->rotate_points($expolygon, $rotate_vector);
     
-    my $expolygon_off = $expolygon->offset_ex(scale $params{flow_spacing}/2)->[0];
-    return {} if !defined $expolygon_off;  # skip some very small polygons (which shouldn't arrive here)
+    my $flow_spacing        = $params{flow_spacing};
+    my $min_spacing         = scale $params{flow_spacing};
+    my $line_spacing        = $min_spacing / $params{density};
+    my $line_oscillation    = $line_spacing - $min_spacing;
+    my $is_line_pattern     = $self->isa('Slic3r::Fill::Line');
+    my $bounding_box        = $expolygon->bounding_box;
     
-    my $flow_spacing = $params{flow_spacing};
-    my $min_spacing = scale $params{flow_spacing};
-    my $distance_between_lines = $min_spacing / $params{density};
-    my $line_oscillation = $distance_between_lines - $min_spacing;
-    my $is_line_pattern = $self->isa('Slic3r::Fill::Line');
-    
-    my $cache_id = sprintf "d%s_s%.2f_a%.2f",
-        $params{density}, $params{flow_spacing}, $rotate_vector->[0][0];
+    # define flow spacing according to requested density
+    if ($params{density} == 1 && !$params{dont_adjust}) {
+        $line_spacing = $self->adjust_solid_spacing(
+            width       => $bounding_box->size->[X],
+            distance    => $line_spacing,
+        );
+        $flow_spacing = unscale $line_spacing;
+    } else {
+        # extend bounding box so that our pattern will be aligned with other layers
+        # $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
+        $bounding_box->extents->[X][MIN] -= $bounding_box->x_min;
+        $bounding_box->extents->[Y][MIN] -= $bounding_box->y_min;
+    }
     
-    if (!$self->cache->{$cache_id}) {
-        # compute bounding box
-        my $bounding_box;
-        {
-            my $bb_polygon = $self->bounding_box->polygon;
-            $bb_polygon->scale(sqrt 2);
-            $self->rotate_points($bb_polygon, $rotate_vector);
-            $bounding_box = $bb_polygon->bounding_box;
-        }
-        
-        # define flow spacing according to requested density
-        if ($params{density} == 1 && !$params{dont_adjust}) {
-            $distance_between_lines = $self->adjust_solid_spacing(
-                width       => $bounding_box->size->[X],
-                distance    => $distance_between_lines,
-            );
-            $flow_spacing = unscale $distance_between_lines;
+    # generate the basic pattern
+    my $i               = 0;
+    my $x               = $bounding_box->x_min;
+    my $x_max           = $bounding_box->x_max + scaled_epsilon;
+    my @vertical_lines  = ();
+    while ($x <= $x_max) {
+        my $vertical_line = Slic3r::Line->new([$x, $bounding_box->y_max], [$x, $bounding_box->y_min]);
+        if ($is_line_pattern && $i % 2) {
+            $vertical_line->[A][X] += $line_oscillation;
+            $vertical_line->[B][X] -= $line_oscillation;
         }
-        
-        # generate the basic pattern
-        my $x = $bounding_box->x_min;
-        my @vertical_lines = ();
-        for (my $i = 0; $x <= $bounding_box->x_max + scaled_epsilon; $i++) {
-            my $vertical_line = Slic3r::Line->new([$x, $bounding_box->y_max], [$x, $bounding_box->y_min]);
-            if ($is_line_pattern && $i % 2) {
-                $vertical_line->[A][X] += $line_oscillation;
-                $vertical_line->[B][X] -= $line_oscillation;
-            }
-            push @vertical_lines, $vertical_line;
-            $x += $distance_between_lines;
-        }
-        
-        $self->cache->{$cache_id} = [@vertical_lines];
+        push @vertical_lines, $vertical_line;
+        $i++;
+        $x += $line_spacing;
     }
     
     # clip paths against a slightly offsetted expolygon, so that the first and last paths
     # are kept even if the expolygon has vertical sides
+    # the minimum offset for preventing edge lines from being clipped is scaled_epsilon;
+    # however we use a larger offset to support expolygons with slightly skewed sides and 
+    # not perfectly straight
     my @polylines = map Slic3r::Polyline->new(@$_),
         @{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection(
-            [ map $_->pp, @{ $expolygon->offset_ex(scaled_epsilon) } ],
-            [ map $_->pp, @{ $self->cache->{$cache_id} } ],
+            [ map $_->pp, @{$expolygon->offset_ex($line_spacing*0.05)} ],
+            [ map $_->pp, @vertical_lines ],
         ) };
     
     # connect lines
     unless ($params{dont_connect}) {
+        my ($expolygon_off) = @{$expolygon->offset_ex(scale $params{flow_spacing}/2)};
         my $collection = Slic3r::Polyline::Collection->new(
             polylines => [ @polylines ],
         );
         @polylines = ();
         
         my $tolerance = 10 * scaled_epsilon;
-        my $diagonal_distance = $distance_between_lines * 2;
+        my $diagonal_distance = $line_spacing * 2;
         my $can_connect = $is_line_pattern
             ? sub {
-                ($_[X] >= ($distance_between_lines - $line_oscillation) - $tolerance) && ($_[X] <= ($distance_between_lines + $line_oscillation) + $tolerance)
+                ($_[X] >= ($line_spacing - $line_oscillation) - $tolerance) && ($_[X] <= ($line_spacing + $line_oscillation) + $tolerance)
                     && $_[Y] <= $diagonal_distance
             }
             : sub { $_[X] <= $diagonal_distance && $_[Y] <= $diagonal_distance };

+ 1 - 1
lib/Slic3r/Format/STL.pm

@@ -10,7 +10,7 @@ sub read_file {
     my $tmesh = Slic3r::TriangleMesh::XS->new;
     $tmesh->ReadSTLFile(Slic3r::encode_path($file));
     $tmesh->Repair;
-    my ($vertices, $facets) = @{$tmesh->ToPerl};
+    my ($vertices, $facets) = ($tmesh->vertices, $tmesh->facets);
     
     my $model = Slic3r::Model->new;
     my $object = $model->add_object(vertices => $vertices, mesh_stats => $tmesh->stats);

+ 24 - 8
lib/Slic3r/GCode.pm

@@ -3,13 +3,14 @@ use Moo;
 
 use List::Util qw(min max first);
 use Slic3r::ExtrusionPath ':roles';
-use Slic3r::Geometry qw(scale unscale scaled_epsilon points_coincide PI X Y B);
+use Slic3r::Geometry qw(epsilon scale unscale scaled_epsilon points_coincide PI X Y B);
 use Slic3r::Geometry::Clipper qw(union_ex);
 use Slic3r::Surface ':types';
 
 has 'config'             => (is => 'ro', required => 1);
 has 'extruders'          => (is => 'ro', default => sub {0}, required => 1);
 has 'multiple_extruders' => (is => 'lazy');
+has 'enable_loop_clipping' => (is => 'rw', default => sub {1});
 has 'enable_wipe'        => (is => 'lazy');   # at least one extruder has wipe enabled
 has 'layer_count'        => (is => 'ro', required => 1 );
 has 'layer'              => (is => 'rw');
@@ -118,22 +119,31 @@ sub change_layer {
     return $gcode;
 }
 
-# this method accepts Z in scaled coordinates
+# this method accepts Z in unscaled coordinates
 sub move_z {
     my $self = shift;
     my ($z, $comment) = @_;
     
-    $z *= &Slic3r::SCALING_FACTOR;
     $z += $self->config->z_offset;
     
     my $gcode = "";
     my $current_z = $self->z;
-    if (!defined $current_z || $current_z != ($z + $self->lifted)) {
+    if (!defined $self->z || $z > $self->z) {
+        # if we're going over the current Z we won't be lifted anymore
+        $self->lifted(0);
+        
+        # this retraction may alter $self->z
         $gcode .= $self->retract(move_z => $z) if $self->extruder->retract_layer_change;
         $self->speed('travel');
         $gcode .= $self->G0(undef, $z, 0, $comment || ('move to next layer (' . $self->layer->id . ')'))
-            unless ($current_z // -1) != ($self->z // -1);
+            if !defined $self->z || abs($z - ($self->z - $self->lifted)) > epsilon;
         $gcode .= $self->move_z_callback->() if defined $self->move_z_callback;
+    } elsif ($z < $self->z && $z > ($self->z - $self->lifted + epsilon)) {
+        # we're moving to a layer height which is greater than the nominal current one
+        # (nominal = actual - lifted) and less than the actual one.  we're basically
+        # advancing to next layer, whose nominal Z is still lower than the previous
+        # layer Z with lift.
+        $self->lifted($self->z - $z);
     }
     
     return $gcode;
@@ -195,7 +205,8 @@ sub extrude_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
     # we discard it in that case
-    $extrusion_path->clip_end(scale $extrusion_path->flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING);
+    $extrusion_path->clip_end(scale $extrusion_path->flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING)
+        if $self->enable_loop_clipping;
     return '' if !@{$extrusion_path->polyline};
     
     my @paths = ();
@@ -346,8 +357,12 @@ sub travel_to {
     # build a more complete configuration space
     $travel->translate(-$self->shift_x, -$self->shift_y);
     
+    # skip retraction if the travel move is contained in an island in the current layer
+    # *and* in an island in the upper layer (so that the ooze will not be visible)
     if ($travel->length < scale $self->extruder->retract_before_travel
-        || ($self->config->only_retract_when_crossing_perimeters && defined first { $_->encloses_line($travel, scaled_epsilon) } @{$self->layer->upper_layer_slices})
+        || ($self->config->only_retract_when_crossing_perimeters
+            && (first { $_->encloses_line($travel, scaled_epsilon) } @{$self->layer->upper_layer_slices})
+            && (first { $_->encloses_line($travel, scaled_epsilon) } @{$self->layer->slices}))
         || ($role == EXTR_ROLE_SUPPORTMATERIAL && $self->layer->support_islands_enclose_line($travel))
         ) {
         $self->straight_once(0);
@@ -505,6 +520,7 @@ sub unretract {
     
     if ($self->lifted) {
         $self->speed('travel');
+        $gcode .= sprintf ";AAA selfz = %s, lifted = %s\n", $self->z // 'nd', $self->lifted // 'nd';
         $gcode .= $self->G0(undef, $self->z - $self->lifted, 0, 'restore layer Z');
         $self->lifted(0);
     }
@@ -523,7 +539,7 @@ sub unretract {
 
 sub reset_e {
     my $self = shift;
-    return "" if $self->config->gcode_flavor =~ /^(?:mach3|makerware)$/;
+    return "" if $self->config->gcode_flavor =~ /^(?:mach3|makerware|sailfish)$/;
     
     $self->extruder->e(0) if $self->extruder;
     return sprintf "G92 %s0%s\n", $self->config->extrusion_axis, ($self->config->gcode_comments ? ' ; reset extrusion distance' : '')

Some files were not shown because too many files changed in this diff