Use bridge math for the first solid infill layer above sparse infill. #240
This commit is contained in:
parent
3b1e921171
commit
08a72c0824
@ -126,8 +126,8 @@ sub make_fill {
|
||||
my $filler = $Slic3r::Config->fill_pattern;
|
||||
my $density = $Slic3r::Config->fill_density;
|
||||
my $flow_spacing = $layer->infill_flow->spacing;
|
||||
my $is_bridge = $layer->id > 0 && $surface->surface_type == S_TYPE_BOTTOM;
|
||||
my $is_solid = (grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID) ? 1 : 0;
|
||||
my $is_bridge = $layer->id > 0 && $surface->is_bridge;
|
||||
my $is_solid = $surface->is_solid;
|
||||
|
||||
# force 100% density and rectilinear fill for external surfaces
|
||||
if ($surface->surface_type != S_TYPE_INTERNAL) {
|
||||
|
@ -458,7 +458,7 @@ sub process_bridges {
|
||||
($_->surface_type == S_TYPE_BOTTOM && $self->id > 0) || $_->surface_type == S_TYPE_TOP
|
||||
} @{$self->fill_surfaces} or return;
|
||||
|
||||
my @internal_surfaces = grep { $_->surface_type == S_TYPE_INTERNAL || $_->surface_type == S_TYPE_INTERNALSOLID } @{$self->slices};
|
||||
my @internal_surfaces = grep $_->is_internal, @{$self->slices};
|
||||
|
||||
SURFACE: foreach my $surface (@solid_surfaces) {
|
||||
my $expolygon = $surface->expolygon->safety_offset;
|
||||
|
@ -356,6 +356,9 @@ sub export_gcode {
|
||||
$status_cb->(60, "Generating horizontal shells");
|
||||
$_->discover_horizontal_shells for @{$self->objects};
|
||||
$_->clip_fill_surfaces for @{$self->objects};
|
||||
# the following step needs to be done before combination because it may need
|
||||
# to remove only half of the combined infill
|
||||
$_->bridge_over_infill for @{$self->objects};
|
||||
|
||||
# combine fill surfaces to honor the "infill every N layers" option
|
||||
$status_cb->(70, "Combining infill");
|
||||
|
@ -426,6 +426,72 @@ sub clip_fill_surfaces {
|
||||
}
|
||||
}
|
||||
|
||||
sub bridge_over_infill {
|
||||
my $self = shift;
|
||||
|
||||
# calculate the number of layers to remove below each bridged one
|
||||
my $skip = int();
|
||||
|
||||
for my $layer_id (1..$#{$self->layers}) {
|
||||
my $layer = $self->layers->[$layer_id];
|
||||
my $lower_layer = $self->layers->[$layer_id-1];
|
||||
|
||||
foreach my $layerm (@{$layer->regions}) {
|
||||
# compute the areas needing bridge math
|
||||
my @internal_solid = grep $_->surface_type == S_TYPE_INTERNALSOLID, @{$layerm->fill_surfaces};
|
||||
my @lower_internal = grep $_->surface_type == S_TYPE_INTERNAL, map @{$_->fill_surfaces}, @{$lower_layer->regions};
|
||||
my $to_bridge = intersection_ex(
|
||||
[ map $_->p, @internal_solid ],
|
||||
[ map $_->p, @lower_internal ],
|
||||
);
|
||||
next unless @$to_bridge;
|
||||
Slic3r::debugf "Bridging %d internal areas at layer %d\n", scalar(@$to_bridge), $layer_id;
|
||||
|
||||
# build the new collection of fill_surfaces
|
||||
{
|
||||
my @new_surfaces = grep $_->surface_type != S_TYPE_INTERNALSOLID, @{$layerm->fill_surfaces};
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => S_TYPE_INTERNALBRIDGE,
|
||||
), @$to_bridge;
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => S_TYPE_INTERNALSOLID,
|
||||
), @{diff_ex(
|
||||
[ map $_->p, @internal_solid ],
|
||||
[ map @$_, @$to_bridge ],
|
||||
)};
|
||||
@{$layerm->fill_surfaces} = @new_surfaces;
|
||||
}
|
||||
|
||||
# exclude infill from the layers below if needed
|
||||
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
||||
{
|
||||
my $excess = $layerm->infill_flow->bridge_width - $layerm->height;
|
||||
for (my $i = $layer_id-1; $excess >= $self->layers->[$i]->height; $i--) {
|
||||
Slic3r::debugf " skipping infill below those areas at layer %d\n", $i;
|
||||
foreach my $lower_layerm (@{$self->layers->[$i]->regions}) {
|
||||
my @new_surfaces = ();
|
||||
# subtract the area from all types of surfaces
|
||||
foreach my $group (Slic3r::Surface->group(@{$lower_layerm->fill_surfaces})) {
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => $group->[0]->surface_type,
|
||||
), @{diff_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map @$_, @$to_bridge ],
|
||||
)};
|
||||
}
|
||||
@{$lower_layerm->fill_surfaces} = @new_surfaces;
|
||||
}
|
||||
|
||||
$excess -= $self->layers->[$i]->height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub discover_horizontal_shells {
|
||||
my $self = shift;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use warnings;
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSOLID);
|
||||
our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE);
|
||||
our %EXPORT_TAGS = (types => \@EXPORT_OK);
|
||||
|
||||
use constant S_EXPOLYGON => 0;
|
||||
@ -17,6 +17,7 @@ use constant S_TYPE_TOP => 0;
|
||||
use constant S_TYPE_BOTTOM => 1;
|
||||
use constant S_TYPE_INTERNAL => 2;
|
||||
use constant S_TYPE_INTERNALSOLID => 3;
|
||||
use constant S_TYPE_INTERNALBRIDGE => 4;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
@ -51,7 +52,7 @@ sub group {
|
||||
|
||||
my %unique_types = ();
|
||||
foreach my $surface (@surfaces) {
|
||||
my $type = ($params->{merge_solid} && grep { $surface->surface_type == $_ } S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_INTERNALSOLID)
|
||||
my $type = ($params->{merge_solid} && $surface->is_solid)
|
||||
? 'solid'
|
||||
: $surface->surface_type;
|
||||
$type .= "_" . ($surface->bridge_angle // ''); #/
|
||||
@ -89,4 +90,28 @@ sub p {
|
||||
return @{$self->expolygon};
|
||||
}
|
||||
|
||||
sub is_solid {
|
||||
my $self = shift;
|
||||
my $type = $self->surface_type;
|
||||
return $type == S_TYPE_TOP
|
||||
|| $type == S_TYPE_BOTTOM
|
||||
|| $type == S_TYPE_INTERNALSOLID
|
||||
|| $type == S_TYPE_INTERNALBRIDGE;
|
||||
}
|
||||
|
||||
sub is_internal {
|
||||
my $self = shift;
|
||||
my $type = $self->surface_type;
|
||||
return $type == S_TYPE_INTERNAL
|
||||
|| $type == S_TYPE_INTERNALSOLID
|
||||
|| $type == S_TYPE_INTERNALBRIDGE;
|
||||
}
|
||||
|
||||
sub is_bridge {
|
||||
my $self = shift;
|
||||
my $type = $self->surface_type;
|
||||
return $type == S_TYPE_BOTTOM
|
||||
|| $type == S_TYPE_INTERNALBRIDGE;
|
||||
}
|
||||
|
||||
1;
|
||||
|
Loading…
Reference in New Issue
Block a user