Bugfix: when processing with fill_density = 0, top/bottom solid shells were missing regions thinner than 3 * extrusion width. Includes regression test. #1602
Conflicts: lib/Slic3r/Print/Object.pm t/fill.t
This commit is contained in:
parent
42519174cd
commit
ffc891d885
@ -727,7 +727,8 @@ sub discover_horizontal_shells {
|
|||||||
next if $n < 0 || $n > $#{$self->layers};
|
next if $n < 0 || $n > $#{$self->layers};
|
||||||
Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
||||||
|
|
||||||
my $neighbor_fill_surfaces = $self->layers->[$n]->regions->[$region_id]->fill_surfaces;
|
my $neighbor_layerm = $self->layers->[$n]->regions->[$region_id];
|
||||||
|
my $neighbor_fill_surfaces = $neighbor_layerm->fill_surfaces;
|
||||||
my @neighbor_fill_surfaces = map $_->clone, @$neighbor_fill_surfaces; # clone because we will use these surfaces even after clearing the collection
|
my @neighbor_fill_surfaces = map $_->clone, @$neighbor_fill_surfaces; # clone because we will use these surfaces even after clearing the collection
|
||||||
|
|
||||||
# find intersection between neighbor and current layer's surfaces
|
# find intersection between neighbor and current layer's surfaces
|
||||||
@ -746,26 +747,41 @@ sub discover_horizontal_shells {
|
|||||||
);
|
);
|
||||||
next EXTERNAL if !@$new_internal_solid;
|
next EXTERNAL if !@$new_internal_solid;
|
||||||
|
|
||||||
# make sure the new internal solid is wide enough, as it might get collapsed when
|
if ($layerm->config->fill_density == 0) {
|
||||||
# spacing is added in Fill.pm
|
# if we're printing a hollow object we discard any solid shell thinner
|
||||||
|
# than a perimeter width, since it's probably just crossing a sloping wall
|
||||||
|
# and it's not wanted in a hollow print even if it would make sense when
|
||||||
|
# obeying the solid shell count option strictly (DWIM!)
|
||||||
|
my $margin = $neighbor_layerm->flow(FLOW_ROLE_PERIMETER)->scaled_width;
|
||||||
|
my $too_narrow = diff(
|
||||||
|
$new_internal_solid,
|
||||||
|
offset2($new_internal_solid, -$margin, +$margin, CLIPPER_OFFSET_SCALE, JT_MITER, 5),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
$new_internal_solid = $solid = diff(
|
||||||
|
$new_internal_solid,
|
||||||
|
$too_narrow,
|
||||||
|
) if @$too_narrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
# make sure the new internal solid is wide enough, as it might get collapsed
|
||||||
|
# when spacing is added in Fill.pm
|
||||||
{
|
{
|
||||||
|
my $margin = 3 * $layerm->flow(FLOW_ROLE_SOLID_INFILL)->scaled_width; # require at least this size
|
||||||
# we use a higher miterLimit here to handle areas with acute angles
|
# we use a higher miterLimit here to handle areas with acute angles
|
||||||
# in those cases, the default miterLimit would cut the corner and we'd
|
# in those cases, the default miterLimit would cut the corner and we'd
|
||||||
# get a triangle in $too_narrow; if we grow it below then the shell
|
# get a triangle in $too_narrow; if we grow it below then the shell
|
||||||
# would have a different shape from the external surface and we'd still
|
# would have a different shape from the external surface and we'd still
|
||||||
# have the same angle, so the next shell would be grown even more and so on.
|
# have the same angle, so the next shell would be grown even more and so on.
|
||||||
my $margin = 3 * $layerm->flow(FLOW_ROLE_SOLID_INFILL)->scaled_width; # require at least this size
|
|
||||||
my $too_narrow = diff(
|
my $too_narrow = diff(
|
||||||
$new_internal_solid,
|
$new_internal_solid,
|
||||||
offset2($new_internal_solid, -$margin, +$margin, CLIPPER_OFFSET_SCALE, JT_MITER, 5),
|
offset2($new_internal_solid, -$margin, +$margin, CLIPPER_OFFSET_SCALE, JT_MITER, 5),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
# if some parts are going to collapse, use a different strategy according to fill density
|
|
||||||
if (@$too_narrow) {
|
if (@$too_narrow) {
|
||||||
if ($layerm->config->fill_density > 0) {
|
# grow the collapsing parts and add the extra area to the neighbor layer
|
||||||
# if we have internal infill, grow the collapsing parts and add the extra area to
|
# as well as to our original surfaces so that we support this
|
||||||
# the neighbor layer as well as to our original surfaces so that we support this
|
|
||||||
# additional area in the next shell too
|
# additional area in the next shell too
|
||||||
|
|
||||||
# make sure our grown surfaces don't exceed the fill area
|
# make sure our grown surfaces don't exceed the fill area
|
||||||
@ -774,13 +790,6 @@ sub discover_horizontal_shells {
|
|||||||
[ map $_->p, @neighbor_fill_surfaces ],
|
[ map $_->p, @neighbor_fill_surfaces ],
|
||||||
)};
|
)};
|
||||||
$new_internal_solid = $solid = [ @grown, @$new_internal_solid ];
|
$new_internal_solid = $solid = [ @grown, @$new_internal_solid ];
|
||||||
} else {
|
|
||||||
# if we're printing a hollow object, we discard such small parts
|
|
||||||
$new_internal_solid = $solid = diff(
|
|
||||||
$new_internal_solid,
|
|
||||||
$too_narrow,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
41
t/fill.t
41
t/fill.t
@ -2,7 +2,7 @@ use Test::More;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
plan tests => 40;
|
plan tests => 41;
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
use FindBin;
|
use FindBin;
|
||||||
@ -12,7 +12,7 @@ BEGIN {
|
|||||||
use List::Util qw(first);
|
use List::Util qw(first);
|
||||||
use Slic3r;
|
use Slic3r;
|
||||||
use Slic3r::Geometry qw(scale X Y convex_hull);
|
use Slic3r::Geometry qw(scale X Y convex_hull);
|
||||||
use Slic3r::Geometry::Clipper qw(diff_ex);
|
use Slic3r::Geometry::Clipper qw(union diff_ex);
|
||||||
use Slic3r::Surface qw(:types);
|
use Slic3r::Surface qw(:types);
|
||||||
use Slic3r::Test;
|
use Slic3r::Test;
|
||||||
|
|
||||||
@ -218,4 +218,41 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) {
|
|||||||
"solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0";
|
"solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $config = Slic3r::Config->new_from_defaults;
|
||||||
|
$config->set('skirts', 0);
|
||||||
|
$config->set('perimeters', 3);
|
||||||
|
$config->set('fill_density', 0);
|
||||||
|
$config->set('layer_height', 0.2);
|
||||||
|
$config->set('first_layer_height', 0.2);
|
||||||
|
$config->set('nozzle_diameter', [0.35]);
|
||||||
|
$config->set('infill_extruder', 2);
|
||||||
|
$config->set('infill_extrusion_width', 0.52);
|
||||||
|
|
||||||
|
my $print = Slic3r::Test::init_print('A', config => $config);
|
||||||
|
my %infill = (); # Z => [ Line, Line ... ]
|
||||||
|
my $tool = undef;
|
||||||
|
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||||
|
my ($self, $cmd, $args, $info) = @_;
|
||||||
|
|
||||||
|
if ($cmd =~ /^T(\d+)/) {
|
||||||
|
$tool = $1;
|
||||||
|
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||||
|
if ($tool == $config->infill_extruder-1) {
|
||||||
|
my $z = 1 * $self->Z;
|
||||||
|
$infill{$z} ||= [];
|
||||||
|
push @{$infill{$z}}, Slic3r::Line->new_scale(
|
||||||
|
[ $self->X, $self->Y ],
|
||||||
|
[ $info->{new_X}, $info->{new_Y} ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
my $grow_d = scale($config->infill_extrusion_width)/2;
|
||||||
|
my $layer0_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.2} } ]);
|
||||||
|
my $layer1_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.4} } ]);
|
||||||
|
my $diff = [ grep $_->area >= 2*$grow_d**2, @{diff_ex($layer0_infill, $layer1_infill)} ];
|
||||||
|
is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0';
|
||||||
|
}
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
Loading…
Reference in New Issue
Block a user