New option for forcing the generation of interface shells. #1847

This commit is contained in:
Alessandro Ranellucci 2014-03-25 01:11:28 +01:00
parent 6feff7fe53
commit 432a87e73d
10 changed files with 72 additions and 19 deletions

View file

@ -114,7 +114,7 @@ sub change_layer {
if ($layer->id > 0 && ($self->print_config->overhangs || $self->print_config->start_perimeters_at_non_overhang)) {
$self->_layer_overhangs->append(
# clone ExPolygons because they come from Surface objects but will be used outside here
map $_->expolygon, map @{$_->slices->filter_by_type(S_TYPE_BOTTOM)}, @{$layer->regions}
map $_->expolygon, map @{$_->slices->filter_by_type(S_TYPE_BOTTOMBRIDGE)}, @{$layer->regions}
);
}
if ($self->print_config->avoid_crossing_perimeters) {

View file

@ -538,6 +538,10 @@ sub build {
title => 'Ooze prevention',
options => [qw(ooze_prevention standby_temperature_delta)],
},
{
title => 'Advanced',
options => [qw(interface_shells)],
},
]);
$self->add_options_page('Advanced', 'wrench.png', optgroups => [

View file

@ -324,7 +324,8 @@ sub prepare_fill_surfaces {
$_->surface_type(S_TYPE_INTERNAL) for @{$self->fill_surfaces->filter_by_type(S_TYPE_TOP)};
}
if ($self->config->bottom_solid_layers == 0) {
$_->surface_type(S_TYPE_INTERNAL) for @{$self->fill_surfaces->filter_by_type(S_TYPE_BOTTOM)};
$_->surface_type(S_TYPE_INTERNAL)
for @{$self->fill_surfaces->filter_by_type(S_TYPE_BOTTOM)}, @{$self->fill_surfaces->filter_by_type(S_TYPE_BOTTOMBRIDGE)};
}
# turn too small internal regions into solid regions according to the user setting
@ -342,7 +343,7 @@ sub process_external_surfaces {
my $margin = scale &Slic3r::EXTERNAL_INFILL_MARGIN;
my @bottom = ();
foreach my $surface (grep $_->surface_type == S_TYPE_BOTTOM, @surfaces) {
foreach my $surface (grep $_->is_bottom, @surfaces) {
my $grown = $surface->expolygon->offset_ex(+$margin);
# detect bridge direction before merging grown surfaces otherwise adjacent bridges
@ -385,7 +386,7 @@ sub process_external_surfaces {
}
# subtract the new top surfaces from the other non-top surfaces and re-add them
my @other = grep $_->surface_type != S_TYPE_TOP && $_->surface_type != S_TYPE_BOTTOM, @surfaces;
my @other = grep $_->surface_type != S_TYPE_TOP && !$_->is_bottom, @surfaces;
foreach my $group (@{Slic3r::Surface::Collection->new(@other)->group}) {
push @new_surfaces, map $group->[0]->clone(expolygon => $_), @{diff_ex(
[ map $_->p, @$group ],

View file

@ -468,17 +468,21 @@ sub detect_surfaces_type {
};
# comparison happens against the *full* slices (considering all regions)
# unless internal shells are requested
my $upper_layer = $self->layers->[$i+1];
my $lower_layer = $i > 0 ? $self->layers->[$i-1] : undef;
my (@bottom, @top, @internal) = ();
# find top surfaces (difference between current surfaces
# of current layer and upper one)
my @top = ();
if ($upper_layer) {
my $upper_slices = $self->config->interface_shells
? [ map $_->expolygon, @{$upper_layer->regions->[$region_id]->slices} ]
: $upper_layer->slices;
@top = $difference->(
[ map $_->expolygon, @{$layerm->slices} ],
$upper_layer->slices,
$upper_slices,
S_TYPE_TOP,
);
} else {
@ -490,13 +494,30 @@ sub detect_surfaces_type {
# find bottom surfaces (difference between current surfaces
# of current layer and lower one)
my @bottom = ();
if ($lower_layer) {
# lower layer's slices are already Surface objects
@bottom = $difference->(
# any surface lying on the void is a true bottom bridge
push @bottom, $difference->(
[ map $_->expolygon, @{$layerm->slices} ],
$lower_layer->slices,
S_TYPE_BOTTOM,
S_TYPE_BOTTOMBRIDGE,
);
# if user requested internal shells, we need to identify surfaces
# lying on other slices not belonging to this region
if ($self->config->interface_shells) {
# non-bridging bottom surfaces: any part of this layer lying
# on something else, excluding those lying on our own region
my $supported = intersection_ex(
[ map @{$_->expolygon}, @{$layerm->slices} ],
[ map @$_, @{$lower_layer->slices} ],
);
push @bottom, $difference->(
$supported,
[ map $_->expolygon, @{$lower_layer->regions->[$region_id]->slices} ],
S_TYPE_BOTTOM,
);
}
} else {
# if no lower layer, all surfaces of this one are solid
# we clone surfaces because we're going to clear the slices collection
@ -515,7 +536,7 @@ sub detect_surfaces_type {
}
# find internal surfaces (difference between top/bottom surfaces and others)
@internal = $difference->(
my @internal = $difference->(
[ map $_->expolygon, @{$layerm->slices} ],
[ map $_->expolygon, @top, @bottom ],
S_TYPE_INTERNAL,
@ -703,7 +724,7 @@ sub discover_horizontal_shells {
$_->surface_type(S_TYPE_INTERNALSOLID) for @{$layerm->fill_surfaces->filter_by_type(S_TYPE_INTERNAL)};
}
EXTERNAL: foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM) {
EXTERNAL: foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_BOTTOMBRIDGE) {
# find slices of current type for current layer
# 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
@ -822,7 +843,7 @@ sub discover_horizontal_shells {
(expolygon => $_, surface_type => S_TYPE_INTERNALSOLID), @$internal_solid);
# assign top and bottom surfaces to layer
foreach my $s (@{Slic3r::Surface::Collection->new(grep { ($_->surface_type == S_TYPE_TOP) || ($_->surface_type == S_TYPE_BOTTOM) } @neighbor_fill_surfaces)->group}) {
foreach my $s (@{Slic3r::Surface::Collection->new(grep { ($_->surface_type == S_TYPE_TOP) || $_->is_bottom } @neighbor_fill_surfaces)->group}) {
my $solid_surfaces = diff_ex(
[ map $_->p, @$s ],
[ map @$_, @$internal_solid, @$internal ],

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 S_TYPE_INTERNALBRIDGE S_TYPE_INTERNALVOID);
our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_BOTTOMBRIDGE S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE S_TYPE_INTERNALVOID);
our %EXPORT_TAGS = (types => \@EXPORT_OK);
sub p {