diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 5e06e952a..6226f0555 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -332,8 +332,15 @@ sub process_bridges { my $line_between_midpoints = Slic3r::Line->new(@midpoints); $bridge_angle = rad2deg_dir($line_between_midpoints->direction); } elsif (@edges == 1) { - my $line = Slic3r::Line->new($edges[0]->[0], $edges[0]->[-1]); - $bridge_angle = rad2deg_dir($line->direction); + # TODO: this case includes both U-shaped bridges and plain overhangs; + # we need a trapezoidation algorithm to detect the actual bridged area + # and separate it from the overhang area. + # in the mean time, we're treating as overhangs all cases where + # our supporting edge is a straight line + if (@{$edges[0]} > 2) { + my $line = Slic3r::Line->new($edges[0]->[0], $edges[0]->[-1]); + $bridge_angle = rad2deg_dir($line->direction); + } } else { my $center = bounding_box_center([ map @$_, @edges ]); my $x = my $y = 0; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 56b794baa..540c44d90 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -446,14 +446,38 @@ sub infill_every_layers { sub generate_support_material { my $self = shift; + # determine unsupported surfaces + my %layers = (); + my @unsupported_expolygons = (); + { + my (@a, @b) = (); + for (my $i = $#{$self->layers}; $i >=0; $i--) { + my $layer = $self->layers->[$i]; + my @c = (); + if (@b) { + @c = @{diff_ex( + [ map @$_, @b ], + [ map @$_, map $_->expolygon->offset_ex(scale $Slic3r::flow_width), @{$layer->slices} ], + )}; + $layers{$i} = [@c]; + } + @b = @{union_ex([ map @$_, @c, @a ])}; + + # get unsupported surfaces for current layer + @a = map $_->expolygon->offset_ex(scale $Slic3r::flow_spacing * $Slic3r::perimeters), + grep $_->surface_type eq 'bottom' && !defined $_->bridge_angle, + @{$layer->fill_surfaces}; + + $_->simplify(scale $Slic3r::flow_spacing * 3) for @a; + push @unsupported_expolygons, @a; + } + } + return if !@unsupported_expolygons; + # generate paths for the pattern that we're going to use my $support_pattern = []; { - # get all surfaces needing support material - my @surfaces = grep $_->surface_type eq 'bottom' && !defined $_->bridge_angle, - map @{$_->slices}, grep $_->id > 0, @{$self->layers} or return; - - my @support_material_areas = @{union_ex([ map $_->p, @surfaces ])}; + my @support_material_areas = @{union_ex([ map @$_, @unsupported_expolygons ])}; for (1..$Slic3r::perimeters+1) { foreach my $expolygon (@support_material_areas) { @@ -497,28 +521,6 @@ sub generate_support_material { ); } - # now determine where to apply the pattern below unsupported surfaces - my %layers = (); - { - my (@a, @b) = (); - for (my $i = $#{$self->layers}; $i >=0; $i--) { - my $layer = $self->layers->[$i]; - my @c = (); - if (@b) { - @c = @{diff_ex( - [ map @$_, @b ], - [ map @$_, map $_->expolygon->offset_ex(scale $Slic3r::flow_width), @{$layer->slices} ], - )}; - $layers{$i} = [@c]; - } - @b = @{union_ex([ map @$_, @c, @a ])}; - @a = map $_->expolygon->offset_ex(scale 2), - grep $_->surface_type eq 'bottom' && !defined $_->bridge_angle, - @{$layer->slices}; - $_->simplify(scale $Slic3r::flow_spacing * 3) for @a; - } - } - # apply the pattern to layers { my $clip_pattern = sub { diff --git a/lib/Slic3r/Skein.pm b/lib/Slic3r/Skein.pm index 71e5dce29..24b8685d1 100644 --- a/lib/Slic3r/Skein.pm +++ b/lib/Slic3r/Skein.pm @@ -114,15 +114,15 @@ sub go { } } - # free memory - @{$_->fill_surfaces} = () for @{$print->layers}; - # generate support material if ($Slic3r::support_material) { $self->status_cb->(85, "Generating support material"); $print->generate_support_material; } + # free memory (note that support material needs fill_surfaces) + @{$_->fill_surfaces} = () for @{$print->layers}; + # make skirt $self->status_cb->(88, "Generating skirt"); $print->extrude_skirt;