Allow to set shell thickness for top/bottom layers (#4430)

* Fix a warning in PresetEditor line 806.

* Remove min_shell_thickness from the if condition in  LayerRegion.cpp

* Add missing line in spiral vase check.

* Add initial set top shell thickness.

* Add minimum shell thickness for top/bottom layers.

* Some refactoring.

* Some Fixes.

* revert last change.

* a fix.

* Some refactoring.

* Some fix in calculating solid layers count.

* Refactoring in LayerRegion.cpp, Object.pm and PresetEditor.pm
This commit is contained in:
Ahmed Samir 2018-06-07 02:26:03 +02:00 committed by Joseph Lenox
parent 31ba88eaa4
commit 1527cfbb26
8 changed files with 54 additions and 24 deletions

View File

@ -191,6 +191,7 @@ sub validate {
die "Invalid value for --solid-layers\n" if defined $self->solid_layers && $self->solid_layers < 0;
die "Invalid value for --top-solid-layers\n" if $self->top_solid_layers < 0;
die "Invalid value for --bottom-solid-layers\n" if $self->bottom_solid_layers < 0;
die "Invalid value for --min-top-bottom-shell-thickness\n" if $self->min_top_bottom_shell_thickness < 0;
# --gcode-flavor
die "Invalid value for --gcode-flavor\n"

View File

@ -438,7 +438,7 @@ sub options {
layer_height first_layer_height
adaptive_slicing adaptive_slicing_quality match_horizontal_surfaces
perimeters spiral_vase
top_solid_layers min_shell_thickness bottom_solid_layers
top_solid_layers min_shell_thickness min_top_bottom_shell_thickness bottom_solid_layers
extra_perimeters avoid_crossing_perimeters thin_walls overhangs
seam_position external_perimeters_first
fill_density fill_pattern top_infill_pattern bottom_infill_pattern fill_gaps
@ -532,6 +532,8 @@ sub build {
$line->append_option($optgroup->get_option('top_solid_layers'));
$line->append_option($optgroup->get_option('bottom_solid_layers'));
$optgroup->append_line($line);
$optgroup->append_single_option_line('min_top_bottom_shell_thickness');
}
{
my $optgroup = $page->new_optgroup('Quality (slower slicing)');
@ -622,7 +624,7 @@ sub build {
$optgroup->append_single_option_line('dont_support_bridges');
}
}
{
my $page = $self->add_options_page('Speed', 'time.png');
{
@ -802,11 +804,12 @@ sub _update {
$opt_key = "all_keys" if (length($key // '') == 0);
my $config = $self->{config};
if (any { /$opt_key/ } qw(all_keys spiral_vase perimeters top_solid_layers fill_density support_material min_shell_thickness)) {
if ($config->spiral_vase && !($config->perimeters == 1 && $config->min_shell_thickness == 0 && $config->top_solid_layers == 0 && $config->fill_density == 0 && $config->support_material == 0)) {
if (any { /$opt_key/ } qw(all_keys spiral_vase perimeters top_solid_layers fill_density support_material min_shell_thickness min_top_bottom_shell_thickness)) {
if ($config->spiral_vase && !($config->perimeters == 1 && $config->min_shell_thickness == 0 && $config->min_top_bottom_shell_thickness == 0 && $config->top_solid_layers == 0 && $config->fill_density == 0 && $config->support_material == 0)) {
my $dialog = Wx::MessageDialog->new($self,
"The Spiral Vase mode requires:\n"
. "- one perimeter\n"
. "- shell thickness to be 0\n"
. "- no top solid layers\n"
. "- 0% fill density\n"
. "- no support material\n"
@ -816,6 +819,7 @@ sub _update {
my $new_conf = Slic3r::Config->new;
$new_conf->set("perimeters", 1);
$new_conf->set("min_shell_thickness", 0);
$new_conf->set("min_top_bottom_shell_thickness", 0);
$new_conf->set("top_solid_layers", 0);
$new_conf->set("fill_density", 0);
$new_conf->set("support_material", 0);
@ -901,7 +905,7 @@ sub _update {
solid_infill_below_area infill_extruder);
}
my $have_solid_infill = ($config->top_solid_layers > 0) || ($config->bottom_solid_layers > 0);
my $have_solid_infill = ($config->top_solid_layers > 0) || ($config->bottom_solid_layers > 0) || ($config->min_top_bottom_shell_thickness > 0);
if (any { /$opt_key/ } qw(all_keys top_solid_layers bottom_solid_layers)) {
# solid_infill_extruder uses the same logic as in Print::extruders()
$self->get_field($_)->toggle($have_solid_infill)
@ -919,7 +923,7 @@ sub _update {
$self->get_field('gap_fill_speed')->toggle($have_perimeters && $have_infill && $config->fill_gaps);
}
my $have_top_solid_infill = ($config->top_solid_layers > 0) || ($config->min_shell_thickness > 0);
my $have_top_solid_infill = ($config->top_solid_layers > 0) || ($config->min_top_bottom_shell_thickness > 0);
$self->get_field($_)->toggle($have_top_solid_infill)
for qw(top_infill_extrusion_width top_solid_infill_speed);

View File

@ -3,6 +3,7 @@ package Slic3r::Print::Object;
use strict;
use warnings;
use POSIX;
use List::Util qw(min max sum first any);
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(X Y Z PI scale unscale chained_path epsilon);
@ -387,10 +388,21 @@ sub discover_horizontal_shells {
];
next if !@$solid;
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
my $solid_layers = ($type == S_TYPE_TOP)
? $layerm->region->config->top_solid_layers
: $layerm->region->config->bottom_solid_layers;
if ($layerm->region->config->min_top_bottom_shell_thickness > 0) {
my $current_shell_thickness = $solid_layers * $self->get_layer($i)->height;
my $minimum_shell_thickness = $layerm->region->config->min_top_bottom_shell_thickness;
while ($minimum_shell_thickness - $current_shell_thickness > epsilon) {
$solid_layers++;
$current_shell_thickness = $solid_layers * $self->get_layer($i)->height;
}
}
NEIGHBOR: for (my $n = ($type == S_TYPE_TOP) ? $i-1 : $i+1;
abs($n - $i) <= $solid_layers-1;
($type == S_TYPE_TOP) ? $n-- : $n++) {

View File

@ -237,26 +237,25 @@ LayerRegion::prepare_fill_surfaces()
the only meaningful information returned by psPerimeters. */
// if no solid layers are requested, turn top/bottom surfaces to internal
if (this->region()->config.min_shell_thickness == 0) {
if (this->region()->config.top_solid_layers == 0) {
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
if (surface->surface_type == stTop) {
if (this->layer()->object()->config.infill_only_where_needed) {
surface->surface_type = stInternalVoid;
} else {
surface->surface_type = stInternal;
}
if (this->region()->config.top_solid_layers == 0 && this->region()->config.min_top_bottom_shell_thickness <= 0) {
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
if (surface->surface_type == stTop) {
if (this->layer()->object()->config.infill_only_where_needed) {
surface->surface_type = stInternalVoid;
} else {
surface->surface_type = stInternal;
}
}
}
if (this->region()->config.bottom_solid_layers == 0) {
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
surface->surface_type = stInternal;
}
}
if (this->region()->config.bottom_solid_layers == 0 && this->region()->config.min_top_bottom_shell_thickness <= 0) {
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
surface->surface_type = stInternal;
}
}
// turn too small internal regions into solid regions according to the user setting
const float &fill_density = this->region()->config.fill_density;
if (fill_density > 0 && fill_density < 100) {

View File

@ -338,7 +338,9 @@ Print::object_extruders() const
if ((*region)->config.fill_density.value > 0)
extruders.insert((*region)->config.infill_extruder - 1);
if ((*region)->config.top_solid_layers.value > 0 || (*region)->config.bottom_solid_layers.value > 0)
if ((*region)->config.top_solid_layers.value > 0
|| (*region)->config.bottom_solid_layers.value > 0
|| (*region)->config.min_top_bottom_shell_thickness.value > 0)
extruders.insert((*region)->config.solid_infill_extruder - 1);
}

View File

@ -837,6 +837,15 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(0);
def = this->add("min_top_bottom_shell_thickness", coFloat);
def->label = "Minimum shell thickness";
def->category = "Layers and Perimeters";
def->sidetext = "mm";
def->tooltip = "Alternative method of configuring top/bottom layers. If this is above 0 extra solid layers will be generated when necessary";
def->cli = "min-vertical-shell-thickness=f";
def->min = 0;
def->default_value = new ConfigOptionFloat(0);
def = this->add("min_layer_height", coFloats);
def->label = "Min";
def->tooltip = "This is the lowest printable layer height for this extruder and limits the resolution for adaptive slicing. Typical values are 0.1 or 0.05.";

View File

@ -256,6 +256,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
ConfigOptionFloatOrPercent infill_overlap;
ConfigOptionFloat infill_speed;
ConfigOptionFloat min_shell_thickness;
ConfigOptionFloat min_top_bottom_shell_thickness;
ConfigOptionBool overhangs;
ConfigOptionInt perimeter_extruder;
ConfigOptionFloatOrPercent perimeter_extrusion_width;
@ -314,7 +315,8 @@ class PrintRegionConfig : public virtual StaticPrintConfig
OPT_PTR(top_infill_pattern);
OPT_PTR(top_solid_infill_speed);
OPT_PTR(top_solid_layers);
OPT_PTR(min_top_bottom_shell_thickness);
return NULL;
};
};

View File

@ -99,6 +99,7 @@ PrintRegion::invalidate_state_by_config(const PrintConfigBase &config)
|| opt_key == "solid_infill_every_layers"
|| opt_key == "bottom_solid_layers"
|| opt_key == "top_solid_layers"
|| opt_key == "min_top_bottom_shell_thickness"
|| opt_key == "min_shell_thickness"
|| opt_key == "infill_extruder"
|| opt_key == "solid_infill_extruder"