From 3164217e3dd5b0e25eb5c996184941d5d2404fbb Mon Sep 17 00:00:00 2001 From: Jaggz H Date: Tue, 11 Apr 2017 12:19:05 -0700 Subject: [PATCH] Addressed logic of enforced supports. There are inconsistent rare crashes which I cannot find as related to my changes. --- lib/Slic3r/Print/Object.pm | 6 +++- lib/Slic3r/Print/SupportMaterial.pm | 51 +++++++++++++++++++---------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 368a234063e..6816c92285b 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -211,7 +211,11 @@ sub generate_support_material { $self->clear_support_layers; - if ((!$self->config->support_material && $self->config->raft_layers == 0) || scalar(@{$self->layers}) < 2) { + if ((!$self->config->support_material + && $self->config->raft_layers == 0 + && $self->config->support_material_enforce_layers == 0) + || scalar(@{$self->layers}) < 2 + ) { $self->set_step_done(STEP_SUPPORTMATERIAL); return; } diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index c533aa4339a..0fa27441c87 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -93,18 +93,21 @@ sub generate { sub contact_area { # $object is Slic3r::Print::Object my ($self, $object) = @_; + my $conf = $self->object_config; # if user specified a custom angle threshold, convert it to radians my $threshold_rad; - if (!($self->object_config->support_material_threshold =~ /%$/)) { - $threshold_rad = deg2rad($self->object_config->support_material_threshold + 1); # +1 makes the threshold inclusive + if (!($conf->support_material_threshold =~ /%$/)) { + $threshold_rad = deg2rad($conf->support_material_threshold + 1); # +1 makes the threshold inclusive Slic3r::debugf "Threshold angle = %d°\n", rad2deg($threshold_rad); } # Build support on a build plate only? If so, then collect top surfaces into $buildplate_only_top_surfaces # and subtract $buildplate_only_top_surfaces from the contact surfaces, so # there is no contact surface supported by a top surface. - my $buildplate_only = $self->object_config->support_material && $self->object_config->support_material_buildplate_only; + my $buildplate_only = + ( $conf->support_material || $conf->support_material_enforce_layers) + && $conf->support_material_buildplate_only; my $buildplate_only_top_surfaces = []; # determine contact areas @@ -115,12 +118,19 @@ sub contact_area { # so $layer_id == 0 means first object layer # and $layer->id == 0 means first print layer (including raft) - if ($self->object_config->raft_layers == 0) { - next if $layer_id == 0; - } elsif (!$self->object_config->support_material) { + # if no raft, and we're at layer 0, skip to layer 1 + if ( $conf->raft_layers == 0 && $layer_id == 0 ) { + next; + } + # with or without raft, if we're above layer 1, we need to quit + # support generation if supports are disabled, or if we're at a high + # enough layer that enforce-supports no longer applies + if ( $layer_id > 0 + && !$conf->support_material + && ($layer_id >= $conf->support_material_enforce_layers) ) { # if we are only going to generate raft just check # the 'overhangs' of the first object layer - last if $layer_id > 0; + last; } my $layer = $object->get_layer($layer_id); @@ -154,12 +164,19 @@ sub contact_area { my $diff; # If a threshold angle was specified, use a different logic for detecting overhangs. - if (defined $threshold_rad - || $layer_id < $self->object_config->support_material_enforce_layers - || ($self->object_config->raft_layers > 0 && $layer_id == 0)) { - my $d = defined $threshold_rad - ? scale $lower_layer->height * ((cos $threshold_rad) / (sin $threshold_rad)) - : 0; + if (($conf->support_material && defined $threshold_rad) + || $layer_id <= $conf->support_material_enforce_layers + || ($conf->raft_layers > 0 && $layer_id == 0)) { + my $d = 0; + my $layer_threshold_rad = $threshold_rad; + if ($layer_id <= $conf->support_material_enforce_layers) { + # Use ~45 deg number for enforced supports if we are in auto + $layer_threshold_rad = deg2rad(75); + } + if (defined $layer_threshold_rad) { + $d = scale $lower_layer->height + * ((cos $layer_threshold_rad) / (sin $layer_threshold_rad)); + } $diff = diff( offset([ map $_->p, @{$layerm->slices} ], -$d), @@ -177,7 +194,7 @@ sub contact_area { } else { $diff = diff( [ map $_->p, @{$layerm->slices} ], - offset([ map @$_, @{$lower_layer->slices} ], +$self->object_config->get_abs_value_over('support_material_threshold', $fw)), + offset([ map @$_, @{$lower_layer->slices} ], +$conf->get_abs_value_over('support_material_threshold', $fw)), ); # collapse very tiny spots @@ -189,7 +206,7 @@ sub contact_area { # outside the lower slice boundary, thus no overhang } - if ($self->object_config->dont_support_bridges) { + if ($conf->dont_support_bridges) { # compute the area of bridging perimeters # Note: this is duplicate code from GCode.pm, we need to refactor @@ -264,7 +281,7 @@ sub contact_area { 1, ); } - } # if ($self->object_config->dont_support_bridges) + } # if ($conf->dont_support_bridges) if ($buildplate_only) { # Don't support overhangs above the top surfaces. @@ -309,7 +326,7 @@ sub contact_area { my $contact_z = $layer->print_z - $self->contact_distance($layer->height, $nozzle_diameter); # ignore this contact area if it's too low - next if $contact_z < $self->object_config->get_value('first_layer_height') - epsilon; + next if $contact_z < $conf->get_value('first_layer_height') - epsilon; $contact{$contact_z} = [ @contact ]; $overhang{$contact_z} = [ @overhang ];