Feature: try to match horizontal surfaces with adaptive slicing

This commit is contained in:
Florens Wasserfall 2016-06-06 14:32:27 +02:00
parent 8485e4bea2
commit 5bb1ffba0d
7 changed files with 69 additions and 6 deletions

View File

@ -6,6 +6,7 @@ use Slic3r::Geometry qw(X Y Z triangle_normal scale unscale);
# public
has 'mesh' => (is => 'ro', required => 1);
has 'size' => (is => 'ro', required => 1);
#private
has 'normal_z' => (is => 'ro', default => sub { [] }); # facet_id => [normal];
@ -158,5 +159,37 @@ sub _facet_cusp_height {
return $cusp;
}
# Returns the distance to the next horizontal facet in Z-dir
# to consider horizontal object features in slice thickness
sub horizontal_facet_distance {
my $self = shift;
my ($z, $max_height) = @_;
$max_height = scale $max_height;
my $ordered_id = $self->current_facet;
while ($ordered_id <= $#{$self->ordered_facets}) {
# facet's minimum is higher than max forward distance -> end loop
if($self->ordered_facets->[$ordered_id]->[1] > $z+$max_height) {
last;
}
# min_z == max_z -> horizontal facet
if($self->ordered_facets->[$ordered_id]->[1] > $z) {
if($self->ordered_facets->[$ordered_id]->[1] == $self->ordered_facets->[$ordered_id]->[2]) {
return unscale $self->ordered_facets->[$ordered_id]->[1] - $z;
}
}
$ordered_id++;
}
# objects maximum?
if($z + $max_height > $self->size) {
return max(unscale $self->size - $z, 0);
}
return unscale $max_height;
}
1;

View File

@ -455,7 +455,7 @@ sub build {
my $self = shift;
$self->init_config_options(qw(
adaptive_slicing cusp_value
adaptive_slicing cusp_value match_horizontal_surfaces
layer_height first_layer_height
perimeters spiral_vase
top_solid_layers bottom_solid_layers
@ -504,6 +504,7 @@ sub build {
$optgroup->append_single_option_line('first_layer_height');
$optgroup->append_single_option_line('adaptive_slicing');
$optgroup->append_single_option_line('cusp_value');
$optgroup->append_single_option_line('match_horizontal_surfaces');
}
{
my $optgroup = $page->new_optgroup('Vertical shells');
@ -787,7 +788,7 @@ sub _update {
my $have_adaptive_slicing = $config->adaptive_slicing;
$self->get_field($_)->toggle($have_adaptive_slicing)
for qw(cusp_value);
for qw(cusp_value match_horizontal_surfaces);
$self->get_field($_)->toggle(!$have_adaptive_slicing)
for qw(layer_height);

View File

@ -108,7 +108,8 @@ sub slice {
}
$adaptive_slicing[$region_id] = Slic3r::AdaptiveSlicing->new(
mesh => $mesh
mesh => $mesh,
size => $self->size->z
);
}
@ -136,6 +137,24 @@ sub slice {
for my $region_id (0 .. ($self->region_count - 1)) {
# get cusp height
my $cusp_height = $adaptive_slicing[$region_id]->cusp_height(scale $slice_z, $cusp_value, $min_height, $max_height);
# check for horizontal features and object size
if($self->config->get_value('match_horizontal_surfaces')) {
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height);
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) {
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist;
# can we shrink the current layer a bit?
if($cusp_height-($min_height-$horizontal_dist) > $min_height) {
# yes we can
$cusp_height = $cusp_height-($min_height-$horizontal_dist);
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height;
}else{
# no, current layer would become too thin
$cusp_height = $cusp_height+$horizontal_dist;
Slic3r::debugf "Widen layer height to %f\n", $cusp_height;
}
}
}
$height = ($id == 0)
? $self->config->get_value('first_layer_height')

View File

@ -46,7 +46,8 @@ my $test = sub {
my $print = Slic3r::Test::init_print('slopy_cube', config => $config);
$print->models->[0]->mesh->repair();
my $adaptive_slicing = Slic3r::AdaptiveSlicing->new(
mesh => Slic3r::Test::mesh('slopy_cube')
mesh => Slic3r::Test::mesh('slopy_cube'),
size => 20
);

View File

@ -585,6 +585,12 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(0.3);
def = this->add("match_horizontal_surfaces", coBool);
def->label = "Match horizontal surfaces";
def->tooltip = "Try to match horizontal surfaces during the slicing process. Matching is not guaranteed, very small surfaces and multiple surfaces with low vertical distance might cause bad results.";
def->cli = "match-horizontal-surfaces!";
def->default_value = new ConfigOptionBool(true);
def = this->add("max_fan_speed", coInt);
def->label = "Max";
def->tooltip = "This setting represents the maximum speed of your fan.";
@ -599,7 +605,7 @@ PrintConfigDef::PrintConfigDef()
def->tooltip = "This is the highest printable layer height for this extruder and limits the resolution for adaptive slicing. Typical values are slightly smaller than nozzle_diameter.";
def->sidetext = "mm";
def->cli = "max-layer-height=f@";
//def->min = 0;
def->min = 0;
{
ConfigOptionFloats* opt = new ConfigOptionFloats();
opt->values.push_back(0.3);
@ -636,7 +642,7 @@ PrintConfigDef::PrintConfigDef()
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.";
def->sidetext = "mm";
def->cli = "min-layer-height=f@";
//def->min = 0;
def->min = 0;
{
ConfigOptionFloats* opt = new ConfigOptionFloats();
opt->values.push_back(0.15);

View File

@ -110,6 +110,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
ConfigOptionBool infill_only_where_needed;
ConfigOptionBool interface_shells;
ConfigOptionFloat layer_height;
ConfigOptionBool match_horizontal_surfaces;
ConfigOptionInt raft_layers;
ConfigOptionEnum<SeamPosition> seam_position;
ConfigOptionBool support_material;
@ -141,6 +142,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
OPT_PTR(infill_only_where_needed);
OPT_PTR(interface_shells);
OPT_PTR(layer_height);
OPT_PTR(match_horizontal_surfaces);
OPT_PTR(raft_layers);
OPT_PTR(seam_position);
OPT_PTR(support_material);

View File

@ -229,6 +229,7 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
|| *opt_key == "xy_size_compensation"
|| *opt_key == "adaptive_slicing"
|| *opt_key == "cusp_value"
|| *opt_key == "match_horizontal_surfaces"
|| *opt_key == "raft_layers") {
steps.insert(posSlice);
} else if (*opt_key == "support_material"