From 1d10cd3da643d4e0ad8717863783c6a51c0cd2ce Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 30 Apr 2014 01:20:18 +0200 Subject: [PATCH] Also remove bridged perimeters area from support material --- lib/Slic3r/Layer/BridgeDetector.pm | 14 +++++++-- lib/Slic3r/Polyline.pm | 19 +++++++++++- lib/Slic3r/Print/SupportMaterial.pm | 45 ++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/lib/Slic3r/Layer/BridgeDetector.pm b/lib/Slic3r/Layer/BridgeDetector.pm index 5cae98f37..7bc97adda 100644 --- a/lib/Slic3r/Layer/BridgeDetector.pm +++ b/lib/Slic3r/Layer/BridgeDetector.pm @@ -77,12 +77,14 @@ sub detect_angle { # we also test angles of each open supporting edge # (this finds the optimal angle for C-shaped supports) - push @angles, map Slic3r::Line->new($_->first_point, $_->last_point)->direction, + push @angles, + map Slic3r::Line->new($_->first_point, $_->last_point)->direction, grep { !$_->first_point->coincides_with($_->last_point) } @edges; # remove duplicates my $min_resolution = PI/180; # 1 degree + @angles = map { ($_ >= &PI-&epsilon) ? ($_-&PI) : $_ } @angles; @angles = sort @angles; for (my $i = 1; $i <= $#angles; ++$i) { if (abs($angles[$i] - $angles[$i-1]) < $min_resolution) { @@ -239,6 +241,14 @@ sub unsupported_edges { $grown_lower, ); + # filter out edges parallel to the bridging angle + for (my $i = 0; $i <= $#$unsupported; ++$i) { + if (first { abs($_->direction - $angle) < epsilon } @{$unsupported->[$i]->lines}) { + splice @$unsupported, $i, 1; + --$i; + } + } + if (0) { require "Slic3r/SVG.pm"; Slic3r::SVG::output( @@ -247,7 +257,7 @@ sub unsupported_edges { green_expolygons => $self->_anchors, red_expolygons => union_ex($grown_lower), no_arrows => 1, - polylines => [ map $_->split_at_first_point, @{$self->expolygon} ], + polylines => \@bridge_edges, red_polylines => $unsupported, ); } diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 7cd431254..53a6d3e3b 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -2,7 +2,7 @@ package Slic3r::Polyline; use strict; use warnings; -use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2); +use Slic3r::Geometry qw(X Y epsilon); use Slic3r::Geometry::Clipper qw(JT_SQUARE); sub new_scale { @@ -26,4 +26,21 @@ sub size { return [ Slic3r::Geometry::size_2D($self) ]; } +sub is_straight { + my ($self) = @_; + + my $last_dir; + foreach my $line (@{$self->lines}) { + my $dir = $line->direction; + if (defined $last_dir) { + if (abs($dir - $last_dir) > epsilon) { + return 0; + } + } + $last_dir = $dir; + } + + return 1; +} + 1; diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index e31ec015c..78bbf0a0e 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -6,7 +6,7 @@ use Slic3r::ExtrusionPath ':roles'; use Slic3r::Flow ':roles'; use Slic3r::Geometry qw(scale scaled_epsilon PI rad2deg deg2rad convex_hull); use Slic3r::Geometry::Clipper qw(offset diff union union_ex intersection offset_ex offset2 - intersection_pl offset2_ex); + intersection_pl offset2_ex diff_pl); use Slic3r::Surface ':types'; has 'print_config' => (is => 'rw', required => 1); @@ -160,16 +160,53 @@ sub contact_area { } if ($self->object_config->dont_support_bridges) { - # TODO: also remove the area of bridging perimeters + # compute the area of bridging perimeters + # Note: this is duplicate code from GCode.pm, we need to refactor + + my $bridged_perimeters; # Polygons + { + my $nozzle_diameter = $self->print_config->get_at('nozzle_diameter', $layerm->region->config->perimeter_extruder-1); + my $lower_grown_slices = offset([ map @$_, @{$lower_layer->slices} ], +scale($nozzle_diameter/2)); + + # TODO: split_at_first_point() could split a bridge mid-way + my @overhang_perimeters = map $_->polygon->split_at_first_point, @{$layerm->perimeters}; + + # workaround for Clipper bug, see Slic3r::Polygon::clip_as_polyline() + $_->[0]->translate(1,0) for @overhang_perimeters; + @overhang_perimeters = @{diff_pl( + \@overhang_perimeters, + $lower_grown_slices, + )}; + + # only consider straight overhangs + @overhang_perimeters = grep $_->is_straight, @overhang_perimeters; + + # only consider overhangs having endpoints inside layer's slices + foreach my $polyline (@overhang_perimeters) { + $polyline->extend_start($fw); + $polyline->extend_end($fw); + } + @overhang_perimeters = grep { + $layer->slices->contains_point($_->first_point) && $layer->slices->contains_point($_->last_point) + } @overhang_perimeters; + + $bridged_perimeters = union([ + map @{$_->grow($fw/2)}, @overhang_perimeters + ]); + } + if (1) { # remove the entire bridges and only support the unsupported edges my @bridges = map $_->expolygon, grep $_->bridge_angle != -1, @{$layerm->fill_surfaces->filter_by_type(S_TYPE_BOTTOMBRIDGE)}; - + $diff = diff( $diff, - [ map @$_, @bridges ], + [ + (map @$_, @bridges), + @$bridged_perimeters, + ], 1, );