Merge branch 'master' into xsdata
Conflicts: lib/Slic3r/Layer/Region.pm lib/Slic3r/Print.pm lib/Slic3r/Print/Object.pm
This commit is contained in:
commit
fa07c512b4
18 changed files with 262 additions and 191 deletions
|
@ -172,6 +172,9 @@ The author of the Silk icon set is Mark James.
|
|||
--bridge-acceleration
|
||||
Overrides firmware's default acceleration for bridges. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--first-layer-acceleration
|
||||
Overrides firmware's default acceleration for first layer. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--default-acceleration
|
||||
Acceleration will be reset to this value after the specific settings above
|
||||
have been applied. (mm/s^2, set zero to disable; default: 130)
|
||||
|
|
|
@ -79,6 +79,7 @@ use constant OVERLAP_FACTOR => 1;
|
|||
use constant SMALL_PERIMETER_LENGTH => (6.5 / SCALING_FACTOR) * 2 * PI;
|
||||
use constant LOOP_CLIPPING_LENGTH_OVER_SPACING => 0.15;
|
||||
use constant INFILL_OVERLAP_OVER_SPACING => 0.45;
|
||||
use constant EXTERNAL_INFILL_MARGIN => 3;
|
||||
|
||||
our $Config;
|
||||
|
||||
|
|
|
@ -369,6 +369,14 @@ our $Options = {
|
|||
type => 'f',
|
||||
default => 0,
|
||||
},
|
||||
'first_layer_acceleration' => {
|
||||
label => 'First layer',
|
||||
tooltip => 'This is the acceleration your printer will use for first layer. Set zero to disable acceleration control for first layer.',
|
||||
sidetext => 'mm/s²',
|
||||
cli => 'first-layer-acceleration=f',
|
||||
type => 'f',
|
||||
default => 0,
|
||||
},
|
||||
|
||||
# accuracy options
|
||||
'layer_height' => {
|
||||
|
@ -1377,6 +1385,11 @@ sub validate {
|
|||
die "Invalid value for --extrusion-multiplier\n"
|
||||
if defined first { $_ <= 0 } @{$self->extrusion_multiplier};
|
||||
|
||||
# --default-acceleration
|
||||
die "Invalid zero value for --default-acceleration when using other acceleration settings\n"
|
||||
if ($self->perimeter_acceleration || $self->infill_acceleration || $self->bridge_acceleration || $self->first_layer_acceleration)
|
||||
&& !$self->default_acceleration;
|
||||
|
||||
# general validation, quick and dirty
|
||||
foreach my $opt_key (keys %$Options) {
|
||||
my $opt = $Options->{$opt_key};
|
||||
|
|
|
@ -127,6 +127,14 @@ sub make_fill {
|
|||
# add spacing between surfaces
|
||||
@surfaces = map @{$_->offset(-$distance_between_surfaces / 2 * &Slic3r::INFILL_OVERLAP_OVER_SPACING)}, @surfaces;
|
||||
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
|
||||
expolygons => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
|
||||
red_expolygons => [ map $_->expolygon, grep $_->is_solid, @surfaces ],
|
||||
);
|
||||
}
|
||||
|
||||
my @fills = ();
|
||||
my @fills_ordering_points = ();
|
||||
SURFACE: foreach my $surface (@surfaces) {
|
||||
|
|
|
@ -32,9 +32,8 @@ sub fill_surface {
|
|||
$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;
|
||||
$bounding_box->extents->[X][MIN] -= $bounding_box->x_min % $line_spacing;
|
||||
$bounding_box->extents->[Y][MIN] -= $bounding_box->y_min % $line_spacing;
|
||||
}
|
||||
|
||||
# generate the basic pattern
|
||||
|
|
|
@ -14,8 +14,9 @@ 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');
|
||||
has '_layer_islands' => (is => 'rw');
|
||||
has '_upper_layer_islands' => (is => 'rw');
|
||||
has '_layer_overhangs' => (is => 'rw');
|
||||
has 'move_z_callback' => (is => 'rw');
|
||||
has 'shift_x' => (is => 'rw', default => sub {0} );
|
||||
has 'shift_y' => (is => 'rw', default => sub {0} );
|
||||
has 'z' => (is => 'rw');
|
||||
|
@ -98,7 +99,14 @@ sub change_layer {
|
|||
|
||||
$self->layer($layer);
|
||||
|
||||
# avoid computing overhangs if they're not needed
|
||||
# avoid computing islands and overhangs if they're not needed
|
||||
if ($self->config->only_retract_when_crossing_perimeters) {
|
||||
$self->_layer_islands([ $layer->islands ]);
|
||||
$self->_upper_layer_islands([ $layer->upper_layer_islands ]);
|
||||
} else {
|
||||
$self->_layer_islands([]);
|
||||
$self->_upper_layer_islands([]);
|
||||
}
|
||||
$self->_layer_overhangs(
|
||||
$layer->id > 0 && ($Slic3r::Config->overhangs || $Slic3r::Config->start_perimeters_at_non_overhang)
|
||||
? [ map $_->expolygon, grep $_->surface_type == S_TYPE_BOTTOM, map @{$_->slices}, @{$layer->regions} ]
|
||||
|
@ -116,6 +124,15 @@ sub change_layer {
|
|||
int(99 * ($layer->id / ($self->layer_count - 1))),
|
||||
($self->config->gcode_comments ? ' ; update progress' : '');
|
||||
}
|
||||
if ($self->config->first_layer_acceleration) {
|
||||
if ($layer->id == 0) {
|
||||
$gcode .= $self->set_acceleration($self->config->first_layer_acceleration);
|
||||
} elsif ($layer->id == 1) {
|
||||
$gcode .= $self->set_acceleration($self->config->default_acceleration);
|
||||
}
|
||||
}
|
||||
|
||||
$gcode .= $self->move_z($layer->print_z);
|
||||
return $gcode;
|
||||
}
|
||||
|
||||
|
@ -137,7 +154,6 @@ sub move_z {
|
|||
$self->speed('travel');
|
||||
$gcode .= $self->G0(undef, $z, 0, $comment || ('move to next layer (' . $self->layer->id . ')'))
|
||||
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
|
||||
|
@ -286,14 +302,16 @@ sub extrude_path {
|
|||
|
||||
# adjust acceleration
|
||||
my $acceleration;
|
||||
if ($self->config->perimeter_acceleration && $path->is_perimeter) {
|
||||
$acceleration = $self->config->perimeter_acceleration;
|
||||
} elsif ($self->config->infill_acceleration && $path->is_fill) {
|
||||
$acceleration = $self->config->infill_acceleration;
|
||||
} elsif ($self->config->infill_acceleration && $path->is_bridge) {
|
||||
$acceleration = $self->config->bridge_acceleration;
|
||||
if (!$self->config->first_layer_acceleration || $self->layer->id != 0) {
|
||||
if ($self->config->perimeter_acceleration && $path->is_perimeter) {
|
||||
$acceleration = $self->config->perimeter_acceleration;
|
||||
} elsif ($self->config->infill_acceleration && $path->is_fill) {
|
||||
$acceleration = $self->config->infill_acceleration;
|
||||
} elsif ($self->config->infill_acceleration && $path->is_bridge) {
|
||||
$acceleration = $self->config->bridge_acceleration;
|
||||
}
|
||||
$gcode .= $self->set_acceleration($acceleration) if $acceleration;
|
||||
}
|
||||
$gcode .= $self->set_acceleration($acceleration) if $acceleration;
|
||||
|
||||
my $area; # mm^3 of extrudate per mm of tool movement
|
||||
if ($path->is_bridge) {
|
||||
|
@ -361,9 +379,9 @@ sub travel_to {
|
|||
# *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
|
||||
&& (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))
|
||||
&& (first { $_->encloses_line($travel, scaled_epsilon) } @{$self->_upper_layer_islands})
|
||||
&& (first { $_->encloses_line($travel, scaled_epsilon) } @{$self->_layer_islands}))
|
||||
|| ($role == EXTR_ROLE_SUPPORTMATERIAL && (first { $_->encloses_line($travel, scaled_epsilon) } @{$self->layer->support_islands}))
|
||||
) {
|
||||
$self->straight_once(0);
|
||||
$self->speed('travel');
|
||||
|
@ -405,9 +423,9 @@ sub _plan {
|
|||
my $need_retract = !$self->config->only_retract_when_crossing_perimeters;
|
||||
if (!$need_retract) {
|
||||
$need_retract = 1;
|
||||
foreach my $slice (@{$self->layer->upper_layer_slices}) {
|
||||
foreach my $island ($self->layer->upper_layer_islands) {
|
||||
# discard the island if at any line is not enclosed in it
|
||||
next if first { !$slice->encloses_line($_, scaled_epsilon) } @travel;
|
||||
next if first { !$island->encloses_line($_, scaled_epsilon) } @travel;
|
||||
# okay, this island encloses the full travel path
|
||||
$need_retract = 0;
|
||||
last;
|
||||
|
|
|
@ -46,23 +46,16 @@ sub process_layer {
|
|||
$self->second_layer_things_done(1);
|
||||
}
|
||||
|
||||
# set new layer, but don't move Z as support material contact areas may need an intermediate one
|
||||
# set new layer - this will change Z and force a retraction if retract_layer_change is enabled
|
||||
$gcode .= $self->gcodegen->change_layer($layer);
|
||||
|
||||
# prepare callback to call as soon as a Z command is generated
|
||||
$self->gcodegen->move_z_callback(sub {
|
||||
$self->gcodegen->move_z_callback(undef); # circular ref or not?
|
||||
return "" if !$Slic3r::Config->layer_gcode;
|
||||
return $Slic3r::Config->replace_options($Slic3r::Config->layer_gcode, {
|
||||
layer_num => $self->gcodegen->layer->id,
|
||||
}) . "\n";
|
||||
});
|
||||
$gcode .= $Slic3r::Config->replace_options($Slic3r::Config->layer_gcode, {
|
||||
layer_num => $self->gcodegen->layer->id,
|
||||
}) . "\n" if $Slic3r::Config->layer_gcode;
|
||||
|
||||
# extrude skirt
|
||||
if ((values %{$self->skirt_done}) < $Slic3r::Config->skirt_height && !$self->skirt_done->{$layer->print_z}) {
|
||||
$self->gcodegen->set_shift(@{$self->shift});
|
||||
$gcode .= $self->gcodegen->set_extruder($self->extruders->[0]); # move_z requires extruder
|
||||
$gcode .= $self->gcodegen->move_z($layer->print_z);
|
||||
$gcode .= $self->gcodegen->set_extruder($self->extruders->[0]);
|
||||
# skip skirt if we have a large brim
|
||||
if ($layer->id < $Slic3r::Config->skirt_height) {
|
||||
# distribute skirt loops across all extruders
|
||||
|
@ -81,8 +74,7 @@ sub process_layer {
|
|||
|
||||
# extrude brim
|
||||
if (!$self->brim_done) {
|
||||
$gcode .= $self->gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]); # move_z requires extruder
|
||||
$gcode .= $self->gcodegen->move_z($layer->print_z);
|
||||
$gcode .= $self->gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_extruder-1]);
|
||||
$self->gcodegen->set_shift(@{$self->shift});
|
||||
$gcode .= $self->gcodegen->extrude_loop($_, 'brim') for @{$self->print->brim};
|
||||
$self->brim_done(1);
|
||||
|
@ -98,7 +90,6 @@ sub process_layer {
|
|||
# extrude support material before other things because it might use a lower Z
|
||||
# and also because we avoid travelling on other things when printing it
|
||||
if ($self->print->has_support_material && $layer->isa('Slic3r::Layer::Support')) {
|
||||
$gcode .= $self->gcodegen->move_z($layer->print_z);
|
||||
if ($layer->support_interface_fills) {
|
||||
$gcode .= $self->gcodegen->set_extruder($self->extruders->[$Slic3r::Config->support_material_interface_extruder-1]);
|
||||
$gcode .= $self->gcodegen->extrude_path($_, 'support material interface')
|
||||
|
@ -111,9 +102,6 @@ sub process_layer {
|
|||
}
|
||||
}
|
||||
|
||||
# set actual Z - this will force a retraction
|
||||
$gcode .= $self->gcodegen->move_z($layer->print_z);
|
||||
|
||||
# tweak region ordering to save toolchanges
|
||||
my @region_ids = 0 .. ($self->print->regions_count-1);
|
||||
if ($self->gcodegen->multiple_extruders) {
|
||||
|
|
|
@ -461,7 +461,7 @@ sub build {
|
|||
},
|
||||
{
|
||||
title => 'Acceleration control (advanced)',
|
||||
options => [qw(perimeter_acceleration infill_acceleration bridge_acceleration default_acceleration)],
|
||||
options => [qw(perimeter_acceleration infill_acceleration bridge_acceleration first_layer_acceleration default_acceleration)],
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ sub union {
|
|||
my ($polygons, $jointype, $safety_offset) = @_;
|
||||
$jointype = PFT_NONZERO unless defined $jointype;
|
||||
$clipper->clear;
|
||||
$clipper->add_subject_polygons($safety_offset ? safety_offset($polygons) : $polygons);
|
||||
$clipper->add_subject_polygons(_convert($safety_offset ? safety_offset($polygons) : $polygons));
|
||||
return [
|
||||
map Slic3r::Polygon->new(@$_),
|
||||
@{ $clipper->execute(CT_UNION, $jointype, $jointype) },
|
||||
|
|
|
@ -23,11 +23,16 @@ sub _trigger_id {
|
|||
$_->_trigger_layer for @{$self->regions || []};
|
||||
}
|
||||
|
||||
sub upper_layer_slices {
|
||||
sub islands {
|
||||
my $self = shift;
|
||||
return @{$self->slices};
|
||||
}
|
||||
|
||||
sub upper_layer_islands {
|
||||
my $self = shift;
|
||||
|
||||
my $upper_layer = $self->object->layers->[ $self->id + 1 ] or return [];
|
||||
return $upper_layer->slices;
|
||||
my $upper_layer = $self->object->layers->[ $self->id + 1 ] or return ();
|
||||
return $upper_layer->islands;
|
||||
}
|
||||
|
||||
sub region {
|
||||
|
@ -59,20 +64,18 @@ sub make_perimeters {
|
|||
$_->make_perimeters for @{$self->regions};
|
||||
}
|
||||
|
||||
sub support_islands_enclose_line {
|
||||
my $self = shift;
|
||||
my ($line) = @_;
|
||||
return 0 if !$self->support_islands; # why can we arrive here if there are no support islands?
|
||||
return (first { $_->encloses_line($line) } @{$self->support_islands}) ? 1 : 0;
|
||||
}
|
||||
|
||||
package Slic3r::Layer::Support;
|
||||
use Moo;
|
||||
extends 'Slic3r::Layer';
|
||||
|
||||
# ordered collection of extrusion paths to fill surfaces for support material
|
||||
has 'support_islands' => (is => 'rw');
|
||||
has 'support_islands' => (is => 'rw', default => sub { [] });
|
||||
has 'support_fills' => (is => 'rw');
|
||||
has 'support_interface_fills' => (is => 'rw');
|
||||
|
||||
sub islands {
|
||||
my $self = shift;
|
||||
return @{$self->slices}, @{$self->support_islands};
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -5,7 +5,8 @@ use List::Util qw(sum first);
|
|||
use Slic3r::ExtrusionPath ':roles';
|
||||
use Slic3r::Geometry qw(PI A B scale chained_path_items points_coincide);
|
||||
use Slic3r::Geometry::Clipper qw(safety_offset union_ex diff_ex intersection_ex
|
||||
offset offset2 offset_ex offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection);
|
||||
offset offset2 offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection
|
||||
union diff);
|
||||
use Slic3r::Surface ':types';
|
||||
|
||||
has 'layer' => (
|
||||
|
@ -131,22 +132,22 @@ sub _merge_loops {
|
|||
# winding order.
|
||||
# TODO: find a faster algorithm for this.
|
||||
my @loops = sort { $a->encloses_point($b->[0]) ? 0 : 1 } @$loops; # outer first
|
||||
$safety_offset //= scale 0.0499;
|
||||
@loops = @{ safety_offset(\@loops, $safety_offset) };
|
||||
my $expolygons = [];
|
||||
while (defined (my $loop = shift @loops)) {
|
||||
if ($loop->is_counter_clockwise) {
|
||||
$expolygons = union_ex([ $loop, map @$_, @$expolygons ]);
|
||||
} else {
|
||||
$expolygons = diff_ex([ map @$_, @$expolygons ], [$loop]);
|
||||
}
|
||||
# we don't perform a safety offset now because it might reverse cw loops
|
||||
my $slices = [];
|
||||
foreach my $loop (@loops) {
|
||||
$slices = $loop->is_counter_clockwise
|
||||
? union([ $loop, @$slices ])
|
||||
: diff($slices, [$loop]);
|
||||
}
|
||||
$expolygons = offset_ex([ map @$_, @$expolygons ], -$safety_offset);
|
||||
|
||||
# perform a safety offset to merge very close facets (TODO: find test case for this)
|
||||
$safety_offset //= scale 0.0499;
|
||||
$slices = offset2_ex($slices, +$safety_offset, -$safety_offset);
|
||||
|
||||
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
||||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
||||
scalar(@$slices), scalar(map $_->holes, @$slices), scalar(@$loops) if $Slic3r::debug;
|
||||
|
||||
return map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL), @$expolygons;
|
||||
return map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_INTERNAL), @$slices;
|
||||
}
|
||||
|
||||
sub make_perimeters {
|
||||
|
@ -174,6 +175,7 @@ sub make_perimeters {
|
|||
# (one more than necessary so that we can detect gaps even after the desired
|
||||
# number of perimeters has been generated)
|
||||
my @last = @{$surface->expolygon};
|
||||
my @this_gaps = ();
|
||||
for my $i (0 .. $loop_number) {
|
||||
# external loop only needs half inset distance
|
||||
my $spacing = ($i == 0)
|
||||
|
@ -194,7 +196,7 @@ sub make_perimeters {
|
|||
# won't shrink the clip polygon to be smaller than intended.
|
||||
offset(\@offsets, +0.5*$spacing + 2),
|
||||
);
|
||||
push @gaps, grep $_->area >= $gap_area_threshold, @$diff;
|
||||
push @gaps, (@this_gaps = grep $_->area >= $gap_area_threshold, @$diff);
|
||||
}
|
||||
|
||||
last if !@offsets || $i == $loop_number;
|
||||
|
@ -203,16 +205,20 @@ sub make_perimeters {
|
|||
@last = @offsets;
|
||||
}
|
||||
|
||||
# make sure we don't infill narrow parts that are already gap-filled
|
||||
# (we only consider this surface's gaps to reduce the diff() complexity)
|
||||
@last = @{diff(\@last, [ map @$_, @this_gaps ])};
|
||||
|
||||
# create one more offset to be used as boundary for fill
|
||||
# we offset by half the perimeter spacing (to get to the actual infill boundary)
|
||||
# and then we offset back and forth by the infill spacing to only consider the
|
||||
# and then we offset back and forth by half the infill spacing to only consider the
|
||||
# non-collapsing regions
|
||||
$self->fill_surfaces->append(
|
||||
@{offset2_ex(
|
||||
[ map $_->simplify_as_polygons(&Slic3r::SCALED_RESOLUTION), @{union_ex(\@last)} ],
|
||||
-($perimeter_spacing/2 + $infill_spacing),
|
||||
+$infill_spacing,
|
||||
)},
|
||||
-($perimeter_spacing/2 + $infill_spacing/2),
|
||||
+$infill_spacing/2,
|
||||
)}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -420,7 +426,7 @@ sub prepare_fill_surfaces {
|
|||
sub process_external_surfaces {
|
||||
my $self = shift;
|
||||
|
||||
my $margin = scale 3; # TODO: ensure this is greater than the total thickness of the perimeters
|
||||
my $margin = scale &Slic3r::EXTERNAL_INFILL_MARGIN;
|
||||
|
||||
my @bottom = ();
|
||||
foreach my $surface (grep $_->surface_type == S_TYPE_BOTTOM, @{$self->fill_surfaces}) {
|
||||
|
|
|
@ -669,8 +669,9 @@ sub make_brim {
|
|||
for my $i (reverse 1 .. $num_loops) {
|
||||
# JT_SQUARE ensures no vertex is outside the given offset distance
|
||||
# -0.5 because islands are not represented by their centerlines
|
||||
# TODO: we need the offset inwards/offset outwards logic to avoid overlapping extrusions
|
||||
push @loops, @{offset2(\@islands, ($i - 1.5) * $flow->scaled_spacing, +1.0 * $flow->scaled_spacing, undef, JT_SQUARE)};
|
||||
# (first offset more, then step back - reverse order than the one used for
|
||||
# perimeters because here we're offsetting outwards)
|
||||
push @loops, @{offset2(\@islands, ($i + 0.5) * $flow->scaled_spacing, -1.0 * $flow->scaled_spacing, undef, JT_SQUARE)};
|
||||
}
|
||||
|
||||
@{$self->brim} = map Slic3r::ExtrusionLoop->new(
|
||||
|
@ -720,7 +721,7 @@ sub write_gcode {
|
|||
# set up our extruder object
|
||||
my $gcodegen = Slic3r::GCode->new(
|
||||
config => $self->config,
|
||||
extruders => $self->extruders,
|
||||
extruders => $self->extruders, # we should only pass the *used* extruders (but maintain the Tx indices right!)
|
||||
layer_count => $self->layer_count,
|
||||
);
|
||||
print $fh "G21 ; set units to millimeters\n" if $Slic3r::Config->gcode_flavor ne 'makerware';
|
||||
|
@ -756,6 +757,10 @@ sub write_gcode {
|
|||
}
|
||||
}
|
||||
|
||||
# always start with first extruder
|
||||
# TODO: make sure we select the first *used* extruder
|
||||
print $fh $gcodegen->set_extruder($self->extruders->[0]);
|
||||
|
||||
# calculate X,Y shift to center print around specified origin
|
||||
my $print_bb = $self->bounding_box;
|
||||
my $print_size = $print_bb->size;
|
||||
|
|
|
@ -562,6 +562,8 @@ sub discover_horizontal_shells {
|
|||
|
||||
Slic3r::debugf "==> DISCOVERING HORIZONTAL SHELLS\n";
|
||||
|
||||
my $margin = scale &Slic3r::EXTERNAL_INFILL_MARGIN;
|
||||
|
||||
for my $region_id (0 .. ($self->print->regions_count-1)) {
|
||||
for (my $i = 0; $i < $self->layer_count; $i++) {
|
||||
my $layerm = $self->layers->[$i]->regions->[$region_id];
|
||||
|
@ -577,9 +579,13 @@ sub discover_horizontal_shells {
|
|||
|
||||
EXTERNAL: foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
|
||||
# find slices of current type for current layer
|
||||
# get both slices and fill_surfaces before the former contains the perimeters area
|
||||
# and the latter contains the enlarged external surfaces
|
||||
my $solid = [ map $_->expolygon, grep $_->surface_type == $type, @{$layerm->slices}, @{$layerm->fill_surfaces} ];
|
||||
# use slices instead of fill_surfaces because they also include the perimeter area
|
||||
# which needs to be propagated in shells; we need to grow slices like we did for
|
||||
# fill_surfaces though. Using both ungrown slices and grown fill_surfaces will
|
||||
# not work in some situations, as there won't be any grown region in the perimeter
|
||||
# area (this was seen in a model where the top layer had one extra perimeter, thus
|
||||
# its fill_surfaces was thinner than the lower layer's infill)
|
||||
my $solid = [ map $_->expolygon->offset_ex($margin), grep $_->surface_type == $type, @{$layerm->slices} ];
|
||||
next if !@$solid;
|
||||
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||
|
||||
|
@ -817,14 +823,10 @@ sub generate_support_material {
|
|||
}
|
||||
|
||||
# shape of contact area
|
||||
my $contact_loops = 1;
|
||||
my $circle_distance = 3 * $flow->scaled_width;
|
||||
my $circle;
|
||||
{
|
||||
# TODO: make sure teeth between circles are compatible with support material flow
|
||||
my $r = 1.5 * $flow->scaled_width;
|
||||
$circle = Slic3r::Polygon->new(map [ $r * cos $_, $r * sin $_ ], (5*PI/3, 4*PI/3, PI, 2*PI/3, PI/3, 0));
|
||||
}
|
||||
my $contact_loops = 1;
|
||||
my $circle_radius = 1.5 * $flow->scaled_width;
|
||||
my $circle_distance = 3 * $circle_radius;
|
||||
my $circle = Slic3r::Polygon->new(map [ $circle_radius * cos $_, $circle_radius * sin $_ ], (5*PI/3, 4*PI/3, PI, 2*PI/3, PI/3, 0));
|
||||
|
||||
# determine contact areas
|
||||
my %contact = (); # contact_z => [ polygons ]
|
||||
|
@ -901,10 +903,18 @@ sub generate_support_material {
|
|||
###$contact_z = $layer->print_z - $layer->height;
|
||||
|
||||
# ignore this contact area if it's too low
|
||||
next if $contact_z < $Slic3r::Config->first_layer_height;
|
||||
next if $contact_z < $Slic3r::Config->get_value('first_layer_height');
|
||||
|
||||
$contact{$contact_z} = [ @contact ];
|
||||
$overhang{$contact_z} = [ @overhang ];
|
||||
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("contact_" . $contact_z . ".svg",
|
||||
expolygons => union_ex(\@contact),
|
||||
red_expolygons => \@overhang,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
my @contact_z = sort keys %contact;
|
||||
|
@ -921,12 +931,17 @@ sub generate_support_material {
|
|||
# ('new' means all the areas that are lower than the last top layer
|
||||
# we considered)
|
||||
my $min_top = min(keys %top) // max(keys %contact);
|
||||
push @$projection, map @{$contact{$_}}, grep { $_ > $layer->print_z && $_ < $min_top } keys %contact;
|
||||
# use <= instead of just < because otherwise we'd ignore any contact regions
|
||||
# having the same Z of top layers
|
||||
push @$projection, map @{$contact{$_}}, grep { $_ > $layer->print_z && $_ <= $min_top } keys %contact;
|
||||
|
||||
# now find whether any projection falls onto this top surface
|
||||
my $touching = intersection($projection, [ map $_->p, @top ]);
|
||||
if (@$touching) {
|
||||
$top{ $layer->print_z } = $touching;
|
||||
# grow top surfaces so that interface and support generation are generated
|
||||
# with some spacing from object - it looks we don't need the actual
|
||||
# top shapes so this can be done here
|
||||
$top{ $layer->print_z } = [ offset($touching, $flow->scaled_spacing) ];
|
||||
}
|
||||
|
||||
# remove the areas that touched from the projection that will continue on
|
||||
|
@ -944,17 +959,15 @@ sub generate_support_material {
|
|||
# if we wanted to apply some special logic to the first support layers lying on
|
||||
# object's top surfaces this is the place to detect them
|
||||
|
||||
# Let's now determine shells (interface layers) and normal support below them.
|
||||
# Let's now fill each support layer by generating shells (interface layers) and
|
||||
# clipping support area to the actual object boundaries.
|
||||
# let's now generate interface layers below contact areas
|
||||
my %interface = (); # layer_id => [ polygons ]
|
||||
my %support = (); # layer_id => [ polygons ]
|
||||
my $interface_layers = $Slic3r::Config->support_material_interface_layers;
|
||||
for my $layer_id (0 .. $#support_layers) {
|
||||
my $z = $support_layers[$layer_id];
|
||||
my $this = $contact{$z} // next;
|
||||
|
||||
# count contact layer as interface layer
|
||||
for (my $i = $layer_id; $i >= 0 && $i > $layer_id-$interface_layers; $i--) {
|
||||
for (my $i = $layer_id-1; $i >= 0 && $i > $layer_id-$interface_layers; $i--) {
|
||||
$z = $support_layers[$i];
|
||||
# Compute interface area on this layer as diff of upper contact area
|
||||
# (or upper interface area) and layer slices.
|
||||
|
@ -963,29 +976,32 @@ sub generate_support_material {
|
|||
# surfaces before performing the diff, but this needs investigation.
|
||||
$this = $interface{$i} = diff(
|
||||
[
|
||||
@$this,
|
||||
@{ $interface{$i} || [] },
|
||||
@$this, # clipped projection of the current contact regions
|
||||
@{ $interface{$i} || [] }, # interface regions already applied to this layer
|
||||
],
|
||||
[
|
||||
@{ $top{$z} || [] },
|
||||
@{ $top{$z} || [] }, # top slices on this layer
|
||||
@{ $contact{$z} || [] }, # contact regions on this layer
|
||||
],
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
# determine what layers does our support belong to
|
||||
for (my $i = $layer_id-$interface_layers; $i >= 0; $i--) {
|
||||
$z = $support_layers[$i];
|
||||
# Compute support area on this layer as diff of upper support area
|
||||
# and layer slices.
|
||||
$this = $support{$i} = diff(
|
||||
}
|
||||
|
||||
# let's now generate support layers under interface layers
|
||||
my %support = (); # layer_id => [ polygons ]
|
||||
{
|
||||
for my $i (reverse 0 .. $#support_layers-1) {
|
||||
my $z = $support_layers[$i];
|
||||
$support{$i} = diff(
|
||||
[
|
||||
@$this,
|
||||
@{ $support{$i} || [] },
|
||||
@{ $support{$i+1} || [] }, # support regions on upper layer
|
||||
@{ $interface{$i+1} || [] }, # interface regions on upper layer
|
||||
],
|
||||
[
|
||||
@{ $top{$z} || [] },
|
||||
@{ $interface{$i} || [] },
|
||||
@{ $top{$z} || [] }, # top slices on this layer
|
||||
@{ $interface{$i} || [] }, # interface regions on this layer
|
||||
@{ $contact{$z} || [] }, # contact regions on this layer
|
||||
],
|
||||
1,
|
||||
);
|
||||
|
@ -1024,13 +1040,30 @@ sub generate_support_material {
|
|||
|
||||
my $process_layer = sub {
|
||||
my ($layer_id) = @_;
|
||||
my $result = { contact => [], interface => [], support => [] };
|
||||
|
||||
$contact{$layer_id} ||= [];
|
||||
$interface{$layer_id} ||= [];
|
||||
$support{$layer_id} ||= [];
|
||||
$contact{$support_layers[$layer_id]} ||= [];
|
||||
$interface{$layer_id} ||= [];
|
||||
$support{$layer_id} ||= [];
|
||||
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("layer_" . $support_layers[$layer_id] . ".svg",
|
||||
red_expolygons => union_ex($contact{$support_layers[$layer_id]}),
|
||||
green_expolygons => union_ex($interface{$layer_id}),
|
||||
);
|
||||
}
|
||||
|
||||
# islands
|
||||
my $result = { contact => [], interface => [], support => [] };
|
||||
$result->{islands} = union_ex([
|
||||
map @$_,
|
||||
$interface{$layer_id},
|
||||
$support{$layer_id},
|
||||
$contact{$support_layers[$layer_id]},
|
||||
]);
|
||||
|
||||
# contact
|
||||
my $contact_infill = [];
|
||||
if ((my $contact = $contact{$support_layers[$layer_id]}) && $contact_loops > 0) {
|
||||
my $overhang = $overhang{$support_layers[$layer_id]};
|
||||
$contact = [ grep $_->is_counter_clockwise, @$contact ];
|
||||
|
@ -1063,11 +1096,8 @@ sub generate_support_material {
|
|||
[ map Slic3r::Polygon->new(@$_)->split_at_first_point, @loops ],
|
||||
) };
|
||||
|
||||
# subtract loops from the contact area to detect the remaining part
|
||||
$interface{$layer_id} = intersection(
|
||||
$interface{$layer_id},
|
||||
[ offset2(\@loops0, -($contact_loops) * $flow->scaled_spacing, +0.5*$flow->scaled_spacing) ],
|
||||
);
|
||||
# add the contact infill area to the interface area
|
||||
$contact_infill = [ offset2(\@loops0, -($contact_loops + 0.5) * $flow->scaled_spacing, +0.5*$flow->scaled_spacing) ];
|
||||
|
||||
# transform loops into ExtrusionPath objects
|
||||
@loops = map Slic3r::ExtrusionPath->pack(
|
||||
|
@ -1079,14 +1109,15 @@ sub generate_support_material {
|
|||
$result->{contact} = [ @loops ];
|
||||
}
|
||||
|
||||
# interface
|
||||
if (@{$interface{$layer_id}}) {
|
||||
# interface and contact infill
|
||||
if (@{$interface{$layer_id}} || @$contact_infill) {
|
||||
$fillers{interface}->angle($interface_angle);
|
||||
|
||||
# steal some space from support
|
||||
$interface{$layer_id} = intersection(
|
||||
[ offset($interface{$layer_id}, scale 3) ],
|
||||
[ @{$interface{$layer_id}}, @{$support{$layer_id}} ],
|
||||
[ offset([ map @$_, $interface{$layer_id}, $contact_infill ], scale 3) ],
|
||||
[ map @$_, $interface{$layer_id}, $support{$layer_id}, $contact_infill ],
|
||||
undef, 1,
|
||||
);
|
||||
$support{$layer_id} = diff(
|
||||
$support{$layer_id},
|
||||
|
@ -1094,7 +1125,7 @@ sub generate_support_material {
|
|||
);
|
||||
|
||||
my @paths = ();
|
||||
foreach my $expolygon (offset_ex($interface{$layer_id}, -$flow->scaled_width/2)) {
|
||||
foreach my $expolygon (@{union_ex($interface{$layer_id})}) {
|
||||
my @p = $fillers{interface}->fill_surface(
|
||||
Slic3r::Surface->new(expolygon => $expolygon),
|
||||
density => $interface_density,
|
||||
|
@ -1121,7 +1152,7 @@ sub generate_support_material {
|
|||
my $flow_spacing = $flow->spacing;
|
||||
|
||||
# TODO: use offset2_ex()
|
||||
my $to_infill = offset_ex(union($support{$layer_id}), -$flow->scaled_width/2);
|
||||
my $to_infill = union_ex($support{$layer_id}, undef, 1);
|
||||
my @paths = ();
|
||||
|
||||
# base flange
|
||||
|
@ -1161,14 +1192,19 @@ sub generate_support_material {
|
|||
), @p;
|
||||
}
|
||||
|
||||
$result->{support} = [ @paths ];
|
||||
push @{$result->{support}}, @paths;
|
||||
}
|
||||
|
||||
# islands
|
||||
$result->{islands} = union_ex([
|
||||
@{$interface{$layer_id} || []},
|
||||
@{$support{$layer_id} || []},
|
||||
]);
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("islands_" . $support_layers[$layer_id] . ".svg",
|
||||
red_expolygons => union_ex($contact{$support_layers[$layer_id]} || []),
|
||||
green_expolygons => union_ex($interface{$layer_id} || []),
|
||||
red_polylines => [ map $_->unpack->polyline, @{$result->{contact}} ],
|
||||
green_polylines => [ map $_->unpack->polyline, @{$result->{interface}} ],
|
||||
polylines => [ map $_->unpack->polyline, @{$result->{support}} ],
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
@ -1183,6 +1219,7 @@ sub generate_support_material {
|
|||
my $support_collection = Slic3r::ExtrusionPath::Collection->new(paths => $result->{support});
|
||||
$layer->support_fills($support_collection) if @{$support_collection->paths} > 0;
|
||||
|
||||
# TODO: use a Slic3r::ExPolygon::Collection
|
||||
$layer->support_islands($result->{islands});
|
||||
};
|
||||
Slic3r::parallelize(
|
||||
|
|
|
@ -34,33 +34,36 @@ sub svg {
|
|||
}
|
||||
|
||||
sub output {
|
||||
my ($filename, %things) = @_;
|
||||
my ($filename, @things) = @_;
|
||||
|
||||
my $svg = svg();
|
||||
my $arrows = 1;
|
||||
|
||||
foreach my $type (qw(expolygons red_expolygons green_expolygons)) {
|
||||
next if !$things{$type};
|
||||
my ($colour) = $type =~ /^(red|green)_/;
|
||||
my $g = $svg->group(
|
||||
style => {
|
||||
'stroke-width' => 2,
|
||||
'stroke' => $colour || 'black',
|
||||
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||
'fill-type' => $filltype,
|
||||
},
|
||||
);
|
||||
foreach my $expolygon (@{$things{$type}}) {
|
||||
my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon;
|
||||
$g->path(
|
||||
d => $points,
|
||||
while (my $type = shift @things) {
|
||||
my $value = shift @things;
|
||||
|
||||
if ($type eq 'no_arrows') {
|
||||
$arrows = 0;
|
||||
} elsif ($type =~ /^(?:(.+?)_)?expolygons$/) {
|
||||
my $colour = $1;
|
||||
|
||||
my $g = $svg->group(
|
||||
style => {
|
||||
'stroke-width' => 2,
|
||||
'stroke' => $colour || 'black',
|
||||
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||
'fill-type' => $filltype,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $type (qw(polygons polylines white_polygons green_polygons red_polygons red_polylines)) {
|
||||
if ($things{$type}) {
|
||||
my $method = $type =~ /polygons/ ? 'polygon' : 'polyline';
|
||||
my ($colour) = $type =~ /^(red|green)_/;
|
||||
foreach my $expolygon (@$value) {
|
||||
my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon;
|
||||
$g->path(
|
||||
d => $points,
|
||||
);
|
||||
}
|
||||
} elsif ($type =~ /^(?:(.+?)_)?(polygon|polyline)s$/) {
|
||||
my ($colour, $method) = ($1, $2);
|
||||
|
||||
my $g = $svg->group(
|
||||
style => {
|
||||
'stroke-width' => 2,
|
||||
|
@ -68,7 +71,7 @@ sub output {
|
|||
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||
},
|
||||
);
|
||||
foreach my $polygon (@{$things{$type}}) {
|
||||
foreach my $polygon (@$value) {
|
||||
my $path = $svg->get_path(
|
||||
'x' => [ map($_->[X] * factor(), @$polygon) ],
|
||||
'y' => [ map($_->[Y] * factor(), @$polygon) ],
|
||||
|
@ -76,15 +79,13 @@ sub output {
|
|||
);
|
||||
$g->$method(
|
||||
%$path,
|
||||
'marker-end' => $things{no_arrows} ? "" : "url(#endArrow)",
|
||||
'marker-end' => $arrows ? "" : "url(#endArrow)",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $type (qw(points red_points)) {
|
||||
if ($things{$type}) {
|
||||
my ($colour, $r) = $type eq 'points' ? ('black', 5) : ('red', 3);
|
||||
} elsif ($type =~ /^(?:(.+?)_)?points$/) {
|
||||
my $colour = $1;
|
||||
my $r = $colour eq 'black' ? 5 : 3;
|
||||
|
||||
my $g = $svg->group(
|
||||
style => {
|
||||
'stroke-width' => 2,
|
||||
|
@ -92,25 +93,22 @@ sub output {
|
|||
'fill' => $colour,
|
||||
},
|
||||
);
|
||||
foreach my $point (@{$things{$type}}) {
|
||||
foreach my $point (@$value) {
|
||||
$g->circle(
|
||||
cx => $point->[X] * factor(),
|
||||
cy => $point->[Y] * factor(),
|
||||
r => $r,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $type (qw(lines red_lines green_lines)) {
|
||||
if ($things{$type}) {
|
||||
my ($colour) = $type =~ /^(red|green)_/;
|
||||
} elsif ($type =~ /^(?:(.+?)_)?lines$/) {
|
||||
my $colour = $1;
|
||||
|
||||
my $g = $svg->group(
|
||||
style => {
|
||||
'stroke-width' => 2,
|
||||
},
|
||||
);
|
||||
foreach my $line (@{$things{$type}}) {
|
||||
foreach my $line (@$value) {
|
||||
$g->line(
|
||||
x1 => $line->[0][X] * factor(),
|
||||
y1 => $line->[0][Y] * factor(),
|
||||
|
@ -119,7 +117,7 @@ sub output {
|
|||
style => {
|
||||
'stroke' => $colour || 'black',
|
||||
},
|
||||
'marker-end' => $things{no_arrows} ? "" : "url(#endArrow)",
|
||||
'marker-end' => $arrows ? "" : "url(#endArrow)",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -128,26 +126,6 @@ sub output {
|
|||
write_svg($svg, $filename);
|
||||
}
|
||||
|
||||
sub output_points {
|
||||
my ($print, $filename, $points, $red_points) = @_;
|
||||
return output($print, $filename, points => $points, red_points => $red_points);
|
||||
}
|
||||
|
||||
sub output_polygons {
|
||||
my ($print, $filename, $polygons) = @_;
|
||||
return output($print, $filename, polygons => $polygons);
|
||||
}
|
||||
|
||||
sub output_polylines {
|
||||
my ($print, $filename, $polylines) = @_;
|
||||
return output($print, $filename, polylines => $polylines);
|
||||
}
|
||||
|
||||
sub output_lines {
|
||||
my ($print, $filename, $lines) = @_;
|
||||
return output($print, $filename, lines => $lines);
|
||||
}
|
||||
|
||||
sub write_svg {
|
||||
my ($svg, $filename) = @_;
|
||||
|
||||
|
|
|
@ -563,7 +563,9 @@ sub horizontal_projection {
|
|||
}
|
||||
|
||||
$_->make_counter_clockwise for @f; # do this after scaling, as winding order might change while doing that
|
||||
return union_ex(\@f, 1);
|
||||
|
||||
# the offset factor was tuned using groovemount.stl
|
||||
return union_ex([ offset(\@f, Slic3r::Geometry::scale 0.01) ], 1);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -255,6 +255,9 @@ $j
|
|||
--bridge-acceleration
|
||||
Overrides firmware's default acceleration for bridges. (mm/s^2, set zero
|
||||
to disable; default: $config->{bridge_acceleration})
|
||||
--first-layer-acceleration
|
||||
Overrides firmware's default acceleration for first layer. (mm/s^2, set zero
|
||||
to disable; default: $config->{first_layer_acceleration})
|
||||
--default-acceleration
|
||||
Acceleration will be reset to this value after the specific settings above
|
||||
have been applied. (mm/s^2, set zero to disable; default: $config->{travel_speed})
|
||||
|
|
15
t/fill.t
15
t/fill.t
|
@ -2,7 +2,7 @@ use Test::More;
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 32;
|
||||
plan tests => 33;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
|
@ -51,17 +51,21 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||
|
||||
{
|
||||
my $test = sub {
|
||||
my ($expolygon, $flow_spacing) = @_;
|
||||
my ($expolygon, $flow_spacing, $angle, $density) = @_;
|
||||
|
||||
my $filler = Slic3r::Fill::Rectilinear->new(
|
||||
bounding_box => $expolygon->bounding_box,
|
||||
angle => 0,
|
||||
angle => $angle // 0,
|
||||
);
|
||||
my $surface = Slic3r::Surface->new(
|
||||
surface_type => S_TYPE_BOTTOM,
|
||||
expolygon => $expolygon,
|
||||
);
|
||||
my ($params, @paths) = $filler->fill_surface($surface, flow_spacing => $flow_spacing, density => 1);
|
||||
my ($params, @paths) = $filler->fill_surface(
|
||||
$surface,
|
||||
flow_spacing => $flow_spacing,
|
||||
density => $density // 1,
|
||||
);
|
||||
|
||||
# check whether any part was left uncovered
|
||||
my @grown_paths = map Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2), @paths;
|
||||
|
@ -100,6 +104,9 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||
[[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]]
|
||||
);
|
||||
$test->($expolygon, 0.524341649025257);
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [98,0], [98,10], [0,10] ]);
|
||||
$test->($expolygon, 0.5, 45, 0.99); # non-solid infill
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -99,7 +99,7 @@ use Slic3r::Test;
|
|||
$config->set('first_layer_speed', '100%'); # prevent speed alteration
|
||||
$config->set('layer_height', 0.4);
|
||||
$config->set('first_layer_height', '100%');
|
||||
$config->set('extrusion_width', 0.5);
|
||||
$config->set('extrusion_width', 0.55);
|
||||
$config->set('bottom_solid_layers', 3);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('solid_infill_speed', 99);
|
||||
|
|
Loading…
Reference in a new issue