Better pruning of thin walls to avoid unwanted extra extrusions. Includes regression test. #1794
This commit is contained in:
parent
c1a5cddcd2
commit
8c4a0f23df
4 changed files with 74 additions and 4 deletions
|
@ -175,14 +175,14 @@ sub make_perimeters {
|
||||||
# the minimum thickness of a single loop is:
|
# the minimum thickness of a single loop is:
|
||||||
# width/2 + spacing/2 + spacing/2 + width/2
|
# width/2 + spacing/2 + spacing/2 + width/2
|
||||||
@offsets = @{offset2(\@last, -(0.5*$pwidth + 0.5*$pspacing - 1), +(0.5*$pspacing - 1))};
|
@offsets = @{offset2(\@last, -(0.5*$pwidth + 0.5*$pspacing - 1), +(0.5*$pspacing - 1))};
|
||||||
|
|
||||||
# look for thin walls
|
# look for thin walls
|
||||||
if ($self->config->thin_walls) {
|
if ($self->config->thin_walls) {
|
||||||
my $diff = diff_ex(
|
my $diff = diff_ex(
|
||||||
\@last,
|
\@last,
|
||||||
offset(\@offsets, +0.5*$pwidth),
|
offset(\@offsets, +0.5*$pwidth),
|
||||||
);
|
);
|
||||||
push @thin_walls, grep abs($_->area) >= $gap_area_threshold, @$diff;
|
push @thin_walls, @$diff;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@offsets = @{offset2(\@last, -(1.5*$pspacing - 1), +(0.5*$pspacing - 1))};
|
@offsets = @{offset2(\@last, -(1.5*$pspacing - 1), +(0.5*$pspacing - 1))};
|
||||||
|
@ -305,14 +305,29 @@ sub make_perimeters {
|
||||||
$self->perimeters->append(@loops);
|
$self->perimeters->append(@loops);
|
||||||
|
|
||||||
# process thin walls by collapsing slices to single passes
|
# process thin walls by collapsing slices to single passes
|
||||||
|
my $min_thin_wall_width = $pwidth/3;
|
||||||
|
my $min_thin_wall_length = 2*$pwidth;
|
||||||
|
@thin_walls = @{offset2_ex([ map @$_, @thin_walls ], -0.5*$min_thin_wall_width, +0.5*$min_thin_wall_width)};
|
||||||
if (@thin_walls) {
|
if (@thin_walls) {
|
||||||
|
if (0) {
|
||||||
|
require "Slic3r/SVG.pm";
|
||||||
|
Slic3r::SVG::output(
|
||||||
|
"thin_walls.svg",
|
||||||
|
no_arrows => 1,
|
||||||
|
expolygons => \@thin_walls,
|
||||||
|
red_polylines => [ map $_->polygon->split_at_first_point, @{$self->perimeters} ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
my @p = map $_->medial_axis($pspacing), @thin_walls;
|
my @p = map $_->medial_axis($pspacing), @thin_walls;
|
||||||
my @paths = ();
|
my @paths = ();
|
||||||
for my $p (@p) {
|
for my $p (@p) {
|
||||||
|
next if $p->length < $min_thin_wall_length;
|
||||||
my %params = (
|
my %params = (
|
||||||
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||||
flow_spacing => $self->perimeter_flow->spacing,
|
flow_spacing => $self->perimeter_flow->spacing,
|
||||||
);
|
);
|
||||||
|
printf "len = %s\n", unscale($p->length);
|
||||||
push @paths, $p->isa('Slic3r::Polygon')
|
push @paths, $p->isa('Slic3r::Polygon')
|
||||||
? Slic3r::ExtrusionLoop->new(polygon => $p, %params)
|
? Slic3r::ExtrusionLoop->new(polygon => $p, %params)
|
||||||
: Slic3r::ExtrusionPath->new(polyline => $p, %params);
|
: Slic3r::ExtrusionPath->new(polyline => $p, %params);
|
||||||
|
|
|
@ -50,7 +50,7 @@ sub output {
|
||||||
|
|
||||||
my $g = $svg->group(
|
my $g = $svg->group(
|
||||||
style => {
|
style => {
|
||||||
'stroke-width' => 2,
|
'stroke-width' => 0,
|
||||||
'stroke' => $colour || 'black',
|
'stroke' => $colour || 'black',
|
||||||
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||||
'fill-type' => $filltype,
|
'fill-type' => $filltype,
|
||||||
|
@ -68,7 +68,7 @@ sub output {
|
||||||
|
|
||||||
my $g = $svg->group(
|
my $g = $svg->group(
|
||||||
style => {
|
style => {
|
||||||
'stroke-width' => 2,
|
'stroke-width' => ($method eq 'polyline') ? 1 : 0,
|
||||||
'stroke' => $colour || 'black',
|
'stroke' => $colour || 'black',
|
||||||
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because one or more lines are too long
48
t/thin.t
Normal file
48
t/thin.t
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use Test::More tests => 1;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
use FindBin;
|
||||||
|
use lib "$FindBin::Bin/../lib";
|
||||||
|
}
|
||||||
|
|
||||||
|
use Slic3r;
|
||||||
|
use List::Util qw(first);
|
||||||
|
use Slic3r::Geometry qw(epsilon);
|
||||||
|
use Slic3r::Test;
|
||||||
|
|
||||||
|
{
|
||||||
|
my $config = Slic3r::Config->new_from_defaults;
|
||||||
|
$config->set('layer_height', 0.2);
|
||||||
|
$config->set('first_layer_height', '100%');
|
||||||
|
$config->set('extrusion_width', 0.5);
|
||||||
|
$config->set('first_layer_extrusion_width', '200%'); # check this one too
|
||||||
|
$config->set('skirts', 0);
|
||||||
|
$config->set('thin_walls', 1);
|
||||||
|
|
||||||
|
my $print = Slic3r::Test::init_print('gt2_teeth', config => $config);
|
||||||
|
|
||||||
|
my %extrusion_paths = (); # Z => count of continuous extrusions
|
||||||
|
my $extruding = 0;
|
||||||
|
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||||
|
my ($self, $cmd, $args, $info) = @_;
|
||||||
|
|
||||||
|
if ($cmd eq 'G1') {
|
||||||
|
if ($info->{extruding} && $info->{dist_XY}) {
|
||||||
|
if (!$extruding) {
|
||||||
|
$extrusion_paths{$self->Z} //= 0;
|
||||||
|
$extrusion_paths{$self->Z}++;
|
||||||
|
}
|
||||||
|
$extruding = 1;
|
||||||
|
} else {
|
||||||
|
$extruding = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ok !(first { $_ != 3 } values %extrusion_paths),
|
||||||
|
'no superfluous thin walls are generated for toothed profile';
|
||||||
|
}
|
||||||
|
|
||||||
|
__END__
|
Loading…
Reference in a new issue