Browse Source

Also remove bridged perimeters area from support material

Alessandro Ranellucci 11 years ago
parent
commit
1d10cd3da6
3 changed files with 71 additions and 7 deletions
  1. 12 2
      lib/Slic3r/Layer/BridgeDetector.pm
  2. 18 1
      lib/Slic3r/Polyline.pm
  3. 41 4
      lib/Slic3r/Print/SupportMaterial.pm

+ 12 - 2
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,
         );
     }

+ 18 - 1
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;

+ 41 - 4
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,
                         );