Browse Source

Improvements to avoid numerical issues in bridge detection and bridge exclusion

Alessandro Ranellucci 11 years ago
parent
commit
010b71e9d4
3 changed files with 19 additions and 16 deletions
  1. 1 1
      lib/Slic3r/Layer/BridgeDetector.pm
  2. 6 12
      lib/Slic3r/Polyline.pm
  3. 12 3
      lib/Slic3r/Print/SupportMaterial.pm

+ 1 - 1
lib/Slic3r/Layer/BridgeDetector.pm

@@ -243,7 +243,7 @@ sub unsupported_edges {
     
     # filter out edges parallel to the bridging angle
     for (my $i = 0; $i <= $#$unsupported; ++$i) {
-        if (first { abs($_->direction - $angle) < epsilon } @{$unsupported->[$i]->lines}) {
+        if ($unsupported->[$i]->is_straight && abs($unsupported->[$i]->lines->[0]->direction < $angle) < epsilon) {
             splice @$unsupported, $i, 1;
             --$i;
         }

+ 6 - 12
lib/Slic3r/Polyline.pm

@@ -2,6 +2,7 @@ package Slic3r::Polyline;
 use strict;
 use warnings;
 
+use List::Util qw(first);
 use Slic3r::Geometry qw(X Y epsilon);
 use Slic3r::Geometry::Clipper qw(JT_SQUARE);
 
@@ -29,18 +30,11 @@ sub size {
 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;
+    # Check that each segment's direction is equal to the line connecting
+    # first point and last point. (Checking each line against the previous
+    # one would have caused the error to accumulate.)
+    my $dir = Slic3r::Line->new($self->first_point, $self->last_point)->direction;
+    return !defined first { abs($_->direction - $dir) > epsilon } @{$self->lines};
 }
 
 1;

+ 12 - 3
lib/Slic3r/Print/SupportMaterial.pm

@@ -165,6 +165,8 @@ sub contact_area {
                     
                     my $bridged_perimeters;  # Polygons
                     {
+                        my $bridge_flow = $layerm->flow(FLOW_ROLE_PERIMETER, 1);
+                        
                         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));
                         
@@ -192,9 +194,16 @@ sub contact_area {
                             $layer->slices->contains_point($_->first_point) && $layer->slices->contains_point($_->last_point)
                         } @overhang_perimeters;
                         
-                        $bridged_perimeters = union([
-                            map @{$_->grow($fw/2)}, @overhang_perimeters
-                        ]);
+                        # convert bridging polylines into polygons by inflating them with their thickness
+                        {
+                            # since we're dealing with bridges, we can't assume width is larger than spacing,
+                            # so we take the largest value and also apply safety offset to be ensure no gaps
+                            # are left in between
+                            my $w = max($bridge_flow->scaled_width, $bridge_flow->scaled_spacing);
+                            $bridged_perimeters = union([
+                                map @{$_->grow($w/2 + 10)}, @overhang_perimeters
+                            ]);
+                        }
                     }
                     
                     if (1) {