Use bridge math for the first solid infill layer above sparse infill. #240

This commit is contained in:
Alessandro Ranellucci 2013-02-23 21:39:13 +01:00
parent 3b1e921171
commit 08a72c0824
5 changed files with 99 additions and 5 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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");

View File

@ -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;

View File

@ -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;