Browse Source

overextruding a bit on top of bridge to come back to a correct height

Merill 7 years ago
parent
commit
2749c63b10

+ 1 - 0
resources/profiles/PrusaResearch.ini

@@ -34,6 +34,7 @@ avoid_crossing_perimeters = 0
 bridge_acceleration = 1000
 bridge_angle = 0
 bridge_flow_ratio = 0.8
+over_bridge_flow_ratio = 1.2
 bridge_speed = 20
 brim_width = 0
 clip_multipart_objects = 1

+ 1 - 0
slic3r.pl

@@ -531,6 +531,7 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
                         Set a different extrusion width for support material
     --infill-overlap    Overlap between infill and perimeters (default: $config->{infill_overlap})
     --bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: $config->{bridge_flow_ratio})
+    --over-bridge-flow-ratio Multiplier for extrusion when solid-filling over a bridge (> 0, default: $config->{over_bridge_flow_ratio})
   
    Multiple extruder options:
     --extruder-offset   Offset of each extruder, if firmware doesn't handle the displacement

+ 1 - 0
t/flow.t

@@ -44,6 +44,7 @@ use Slic3r::Test;
     my $config = Slic3r::Config::new_from_defaults;
     $config->set('bridge_speed', 99);
     $config->set('bridge_flow_ratio', 1);
+    $config->set('over_bridge_flow_ratio', 1);
     $config->set('cooling', [ 0 ]);             # to prevent speeds from being altered
     $config->set('first_layer_speed', '100%');  # to prevent speeds from being altered
     

+ 1 - 0
t/perimeters.t

@@ -248,6 +248,7 @@ use Slic3r::Test;
         $config->set('slowdown_below_layer_time', [ 0 ]);
         $config->set('bridge_fan_speed', [ 100 ]);
         $config->set('bridge_flow_ratio', 33);  # arbitrary value
+        $config->set('over_bridge_flow_ratio', 110);  # arbitrary value
         $config->set('overhangs', 1);
         my $print = Slic3r::Test::init_print('overhang', config => $config);
         my %layer_speeds = ();  # print Z => [ speeds ]

+ 13 - 8
xs/src/libslic3r/Fill/Fill.cpp

@@ -63,14 +63,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
             // (we'll use them for comparing compatible groups)
             std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
             for (size_t i = 0; i < groups.size(); ++ i) {
-                // we can only merge solid non-bridge surfaces, so discard
+                // we can only merge solid non-bridge non-overextruded surfaces, so discard
                 // non-solid surfaces
                 const Surface &surface = *groups[i].front();
-                if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
+                if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0) && !surface.is_overBridge()) {
                     group_attrib[i].is_solid = true;
-                    group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
-                    group_attrib[i].pattern = (surface.surface_type == stTop && surface.is_external()) ? layerm.region()->config.top_fill_pattern.value : ipRectilinear;
-                    group_attrib[i].pattern = (surface.surface_type == stBottom && surface.is_external()) ? layerm.region()->config.bottom_fill_pattern.value : ipRectilinear;
+                    group_attrib[i].flow_width = (surface.is_top()) ? top_solid_infill_flow.width : solid_infill_flow.width;
+                    group_attrib[i].pattern = (surface.is_top() && surface.is_external()) ? layerm.region()->config.top_fill_pattern.value : ipRectilinear;
+                    group_attrib[i].pattern = (surface.is_bottom() && surface.is_external()) ? layerm.region()->config.bottom_fill_pattern.value : ipRectilinear;
                 }
             }
             // Loop through solid groups, find compatible groups and append them to this one.
@@ -155,14 +155,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
             continue;
         InfillPattern  fill_pattern = layerm.region()->config.fill_pattern.value;
         double         density      = fill_density;
-        FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
+        FlowRole role = (surface.is_top()) ? frTopSolidInfill :
             (surface.is_solid() ? frSolidInfill : frInfill);
         bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
         
         if (surface.is_solid()) {
             density = 100.;
             fill_pattern = (surface.is_external() && ! is_bridge) ? 
-                (surface.surface_type == stTop ? layerm.region()->config.top_fill_pattern.value : layerm.region()->config.bottom_fill_pattern.value) :
+                (surface.is_top() ? layerm.region()->config.top_fill_pattern.value : layerm.region()->config.bottom_fill_pattern.value) :
                 ipRectilinear;
         } else if (density <= 0)
             continue;
@@ -241,6 +241,11 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
         } else {
             flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
         }
+		
+		float flow_percent = 1;
+		if(surface.is_overBridge()){
+			flow_percent = layerm.region()->config.over_bridge_flow_ratio;
+		}
 
         // Save into layer.
         auto *eec = new ExtrusionEntityCollection();
@@ -254,7 +259,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
                 (surface.is_solid() ?
                     ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
                     erInternalInfill),
-            flow.mm3_per_mm(), flow.width, flow.height);
+            flow.mm3_per_mm()*flow_percent, flow.width*flow_percent, flow.height);
     }
 
     // add thin fill regions

+ 6 - 7
xs/src/libslic3r/LayerRegion.cpp

@@ -121,7 +121,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
         fill_boundaries.reserve(number_polygons(surfaces));
         bool has_infill = this->region()->config.fill_density.value > 0.;
         for (const Surface &surface : this->fill_surfaces.surfaces) {
-            if (surface.surface_type == stTop) {
+            if (surface.is_top()) {
                 // Collect the top surfaces, inflate them and trim them by the bottom surfaces.
                 // This gives the priority to bottom surfaces.
                 surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
@@ -132,13 +132,12 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
                 if (! surface.empty())
                     bridges.push_back(surface);
             }
-            bool internal_surface = surface.surface_type != stTop && ! surface.is_bottom();
             if (has_infill || surface.surface_type != stInternal) {
-                if (internal_surface)
+                if (!surface.is_external())
                     // Make a copy as the following line uses the move semantics.
                     internal.push_back(surface);
                 polygons_append(fill_boundaries, STDMOVE(surface.expolygon));
-            } else if (internal_surface)
+            } else if (!surface.is_external())
                 internal.push_back(STDMOVE(surface));
         }
     }
@@ -304,7 +303,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
                     s2.clear();
                 }
             }
-            if (s1.surface_type == stTop)
+            if (s1.is_top())
                 // Trim the top surfaces by the bottom surfaces. This gives the priority to the bottom surfaces.
                 polys = diff(polys, bottom_polygons);
             surfaces_append(
@@ -357,13 +356,13 @@ LayerRegion::prepare_fill_surfaces()
     // if no solid layers are requested, turn top/bottom surfaces to internal
     if (this->region()->config.top_solid_layers == 0) {
         for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
-            if (surface->surface_type == stTop)
+            if (surface->is_top())
                 surface->surface_type = (this->layer()->object()->config.infill_only_where_needed) ? 
                     stInternalVoid : stInternal;
     }
     if (this->region()->config.bottom_solid_layers == 0) {
         for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
-            if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
+            if (surface->is_bottom())
                 surface->surface_type = stInternal;
         }
     }

+ 1 - 0
xs/src/libslic3r/Print.hpp

@@ -199,6 +199,7 @@ public:
     void process_external_surfaces();
     void discover_vertical_shells();
     void bridge_over_infill();
+	void replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it);
     void _make_perimeters();
     void _infill();
     void clip_fill_surfaces();

+ 15 - 0
xs/src/libslic3r/PrintConfig.cpp

@@ -113,6 +113,17 @@ PrintConfigDef::PrintConfigDef()
     def->min = 0;
     def->default_value = new ConfigOptionFloat(1);
 
+    def = this->add("over_bridge_flow_ratio", coFloat);
+    def->label = L("Over-bridge flow ratio");
+    def->category = L("Advanced");
+    def->tooltip = L("This factor affects the amount of plastic to overextrude "
+                   "when we are filling on top of a bridge surface."
+                   "With a number >1, we can retreive the correct z-height "
+				   "even if the bridged layer has fallen a bit.");
+    def->cli = "over-bridge-flow-ratio=f";
+    def->min = 0;
+    def->default_value = new ConfigOptionFloat(1);
+
     def = this->add("bridge_speed", coFloat);
     def->label = L("Bridges");
     def->category = L("Speed");
@@ -2013,6 +2024,10 @@ std::string FullPrintConfig::validate()
     if (this->bridge_flow_ratio <= 0)
         return "Invalid value for --bridge-flow-ratio";
     
+    // --over-bridge-flow-ratio
+    if (this->over_bridge_flow_ratio <= 0)
+        return "Invalid value for --over-bridge-flow-ratio";
+    
     // extruder clearance
     if (this->extruder_clearance_radius <= 0)
         return "Invalid value for --extruder-clearance-radius";

+ 2 - 0
xs/src/libslic3r/PrintConfig.hpp

@@ -376,6 +376,7 @@ public:
     ConfigOptionFloat               bridge_angle;
     ConfigOptionInt                 bottom_solid_layers;
     ConfigOptionFloat               bridge_flow_ratio;
+    ConfigOptionFloat               over_bridge_flow_ratio;
     ConfigOptionFloat               bridge_speed;
     ConfigOptionBool                ensure_vertical_shell_thickness;
     ConfigOptionEnum<InfillPattern> top_fill_pattern;
@@ -416,6 +417,7 @@ protected:
         OPT_PTR(bridge_angle);
         OPT_PTR(bottom_solid_layers);
         OPT_PTR(bridge_flow_ratio);
+        OPT_PTR(over_bridge_flow_ratio);
         OPT_PTR(bridge_speed);
         OPT_PTR(ensure_vertical_shell_thickness);
         OPT_PTR(top_fill_pattern);

+ 208 - 2
xs/src/libslic3r/PrintObject.cpp

@@ -363,10 +363,18 @@ void PrintObject::_prepare_infill()
     // the following step needs to be done before combination because it may need
     // to remove only half of the combined infill
     this->bridge_over_infill();
+	std::cout<<"INTERNAL BRIDGE ===========================================\n";
+	this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stInternalBridge);
+	std::cout<<"BOTTOM BRIDGE ===========================================\n";
+	this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stBottomBridge);
+	std::cout<<"TOP BRIDGE ===========================================\n";
+	this->replaceSurfaceType( stTop, stTopOverBridge, stInternalBridge);
+	this->replaceSurfaceType( stTop, stTopOverBridge, stBottomBridge);
 
     // combine fill surfaces to honor the "infill every N layers" option
     this->combine_infill();
 
+	
 #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
     for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) {
         for (const Layer *layer : this->layers) {
@@ -435,6 +443,7 @@ void PrintObject::detect_surfaces_type()
                     // unless internal shells are requested
                     Layer       *upper_layer = (idx_layer + 1 < this->layer_count()) ? this->layers[idx_layer + 1] : nullptr;
                     Layer       *lower_layer = (idx_layer > 0) ? this->layers[idx_layer - 1] : nullptr;
+                    Layer       *under_lower_layer = (idx_layer > 1) ? this->layers[idx_layer - 2] : nullptr;
                     // collapse very narrow parts (using the safety offset in the diff is not enough)
                     float        offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
 
@@ -478,6 +487,7 @@ void PrintObject::detect_surfaces_type()
                                 diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true), 
                                 -offset, offset),
                             surface_type_bottom_other);
+							
                         // if user requested internal shells, we need to identify surfaces
                         // lying on other slices not belonging to this region
                         if (interface_shells) {
@@ -494,6 +504,7 @@ void PrintObject::detect_surfaces_type()
                                 stBottom);
                         }
 #endif
+						
                     } else {
                         // if no lower layer, all surfaces of this one are solid
                         // we clone surfaces because we're going to clear the slices collection
@@ -501,6 +512,22 @@ void PrintObject::detect_surfaces_type()
                         for (Surface &surface : bottom)
                             surface.surface_type = surface_type_bottom_1st;
                     }
+					
+					// Any surface lying on the void is a true bottom bridge (an overhang) 
+					// and we have to conpensate if we are over that
+                    // Surfaces bottomOverBridge;
+					// if(under_lower_layer){
+						// surfaces_append(
+							// bottomOverBridge,
+							// offset2_ex(
+								// diff(layerm_slices_surfaces, to_polygons(under_lower_layer->slices), true), 
+								// -offset, offset),
+							// stInternalOverBridge);
+						// std::cout<<idx_layer<<" under_lower_layer "<<under_lower_layer->slices.expolygons.size()<<" > "<<bottomOverBridge.size()<<", bot="<<bottom.size()<<"\n";
+						// for(int i=0;i<under_lower_layer->slices.expolygons.size();i++) std::cout<<" area of under_lower_layer "<<under_lower_layer->slices.expolygons[i].area()<<"\n";
+						// for(int i=0;i<bottom.size();i++) std::cout<<" area of bottom "<<bottom[i].area()<<"\n";
+						// for(int i=0;i<bottomOverBridge.size();i++) std::cout<<" area of overbridge "<<bottomOverBridge[i].area()<<"\n";
+					// }
                     
                     // now, if the object contained a thin membrane, we could have overlapping bottom
                     // and top surfaces; let's do an intersection to discover them and consider them
@@ -522,6 +549,7 @@ void PrintObject::detect_surfaces_type()
                         std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
                         expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top),                           SVG::ExPolygonAttributes("green")));
                         expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom),                        SVG::ExPolygonAttributes("brown")));
+                        expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottomOverBridge),              SVG::ExPolygonAttributes("grey")));
                         expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces),  SVG::ExPolygonAttributes("black")));
                         SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
                     }
@@ -535,6 +563,12 @@ void PrintObject::detect_surfaces_type()
                     {
                         Polygons topbottom = to_polygons(top);
                         polygons_append(topbottom, to_polygons(bottom));
+                        // ExPolygons overExPolygons = diff_ex(to_polygons(bottomOverBridge), topbottom, false);
+						// surfaces_append(surfaces_out,
+                            // overExPolygons,
+                            // stInternalOverBridge);
+						// for(int i=0;i<overExPolygons.size();i++) std::cout<<" area of overExPolygons "<<overExPolygons[i].area()<<"\n";
+                        // polygons_append(topbottom, to_polygons(bottomOverBridge));
                         surfaces_append(surfaces_out,
                             diff_ex(layerm_slices_surfaces, topbottom, false),
                             stInternal);
@@ -1106,6 +1140,178 @@ void PrintObject::bridge_over_infill()
     }
 }
 
+
+/* This method applies overextrude flow to the first internal solid layer above
+   bridge (which is over sparse infill) note: it's almost complete copy/paste from the method behind,
+   i think it should be merged before gitpull that.
+   */
+void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it)
+{
+    BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
+
+    FOREACH_REGION(this->_print, region) {
+        size_t region_id = region - this->_print->regions.begin();
+        
+        FOREACH_LAYER(this, layer_it) {
+            // skip first layer
+            if (layer_it == this->layers.begin()) continue;
+            
+            Layer* layer        = *layer_it;
+            LayerRegion* layerm = layer->regions[region_id];
+            
+            // extract the stInternalSolid surfaces that might be transformed into bridges
+            Polygons internal_solid;
+            layerm->fill_surfaces.filter_by_type(st_to_replace, &internal_solid);
+			
+			double internsolidareainit=0;
+			for (ExPolygon &ex : union_ex(internal_solid)) internsolidareainit+=ex.area();
+			
+			Polygons internal_over_tot_init;
+            layerm->fill_surfaces.filter_by_type(st_replacement, &internal_over_tot_init);
+			double totoverareaInit=0;
+			for (ExPolygon &ex : union_ex(internal_over_tot_init)) totoverareaInit+=ex.area();
+
+			Polygons stBottom_init;
+            layerm->fill_surfaces.filter_by_type(stBottom, &stBottom_init);
+			double bottomeareainit=0;
+			for (ExPolygon &ex : union_ex(stBottom_init)) bottomeareainit+=ex.area();
+
+			Polygons stBottomBridge_init;
+            layerm->fill_surfaces.filter_by_type(stBottomBridge, &stBottomBridge_init);
+			double bottombridgearea=0;
+			for (ExPolygon &ex : union_ex(stBottomBridge_init)) bottombridgearea+=ex.area();
+			
+			Polygons stIntBridge_init;
+            layerm->fill_surfaces.filter_by_type(st_under_it, &stIntBridge_init);
+			double intbridgeareainit=0;
+			for (ExPolygon &ex : union_ex(stIntBridge_init)) intbridgeareainit+=ex.area();
+			
+			std::cout<<"init st_replacement="<<totoverareaInit<<", bottombridgearea="<<bottombridgearea
+			<<", st_to_replace="<<internsolidareainit<<", bottomeareainit="<<bottomeareainit
+			<<", st_under_it="<<intbridgeareainit<<"\n";
+            
+            // check whether the lower area is deep enough for absorbing the extra flow
+            // (for obvious physical reasons but also for preventing the bridge extrudates
+            // from overflowing in 3D preview)
+            ExPolygons to_overextrude;
+            {
+                Polygons to_overextrude_pp = internal_solid;
+                
+                // get previous layer
+                if (int(layer_it - this->layers.begin()) - 1 >= 0) {
+                    const Layer* lower_layer = this->layers[int(layer_it - this->layers.begin()) - 1];
+                    
+                    // iterate through regions and collect internal surfaces
+                    Polygons lower_internal;
+                    FOREACH_LAYERREGION(lower_layer, lower_layerm_it){
+						Polygons lower_internal_OK;
+						Polygons lower_internal_Bridge;
+						Polygons lower_internal_Over;
+                        (*lower_layerm_it)->fill_surfaces.filter_by_type(st_replacement, &lower_internal_OK);
+                        (*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal_Bridge);
+                        (*lower_layerm_it)->fill_surfaces.filter_by_type(st_to_replace, &lower_internal_Over);
+						double okarea =0, bridgearea=0, overarea=0;
+						for (ExPolygon &ex : union_ex(lower_internal_OK)) okarea+=ex.area();
+						for (ExPolygon &ex : union_ex(lower_internal_Bridge)) bridgearea+=ex.area();
+						for (ExPolygon &ex : union_ex(lower_internal_Over)) overarea+=ex.area();
+						std::cout<<"@layer "<<int(layer_it - this->layers.begin())
+							<<" region under  has "<<lower_internal_OK.size()<<" st_replacement : "<<okarea
+							<<" , has "<<lower_internal_Bridge.size()<<" st_under_it: "<<bridgearea
+							<<" , has "<<lower_internal_Over.size()<<" st_to_replace: "<<overarea<<"\n";
+                        (*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
+					}
+						double sumarea=0;
+						for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area();
+						std::cout<<"@layer "<<int(layer_it - this->layers.begin())<<" region under  has "<<union_ex(lower_internal).size()<<" sum bridge : "<<sumarea<<"\n";
+                    
+                    // intersect such lower internal surfaces with the candidate solid surfaces
+                    to_overextrude_pp = intersection(to_overextrude_pp, lower_internal);
+                }
+                
+                // there's no point in overextruding too thin/short regions
+                //FIXME Vojtech: The offset2 function is not a geometric offset, 
+                // therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
+                // The gaps will be filled by a separate region, which makes the infill less stable and it takes longer.
+                // {
+                    // float min_width = float(bridge_flow.scaled_width()) * 3.f;
+                    // to_overextrude_pp = offset2(to_overextrude_pp, -min_width, +min_width);
+                // }
+                
+                if (to_overextrude_pp.empty()) continue;
+                
+                // convert into ExPolygons
+                to_overextrude = union_ex(to_overextrude_pp);
+				double finalarea = 0;
+				for (ExPolygon &ex : to_overextrude) finalarea+=ex.area();
+				std::cout<<"find an overextruding area of "<<finalarea<<" on layer "<<int(layer_it - this->layers.begin())<<"\n";
+            }
+            
+            #ifdef SLIC3R_DEBUG
+            printf("Bridging " PRINTF_ZU " internal areas at layer " PRINTF_ZU "\n", to_overextrude.size(), layer->id());
+            #endif
+            
+            // compute the remaning internal solid surfaces as difference
+            ExPolygons not_to_overextrude = diff_ex(internal_solid, to_polygons(to_overextrude), true);
+            to_overextrude = intersection_ex(to_polygons(to_overextrude), internal_solid, true);
+            // build the new collection of fill_surfaces
+            layerm->fill_surfaces.remove_type(st_to_replace);
+			double overareafinal = 0, solidareafinal=0;
+            for (ExPolygon &ex : to_overextrude){
+				overareafinal += ex.area();
+                layerm->fill_surfaces.surfaces.push_back(Surface(st_replacement, ex));
+			}
+            for (ExPolygon &ex : not_to_overextrude){
+				solidareafinal += ex.area();
+				layerm->fill_surfaces.surfaces.push_back(Surface(st_to_replace, ex));
+			}
+			Polygons internal_over_tot;
+            layerm->fill_surfaces.filter_by_type(stInternalOverBridge, &internal_over_tot);
+			double totoverarea=0;
+			for (ExPolygon &ex : union_ex(internal_over_tot)) totoverarea+=ex.area();
+			std::cout<<"final: st_to_replace="<<solidareafinal<<", st_replacement="<<overareafinal<<", totstInternalOverBridge="<<totoverarea<<"\n";
+            /*
+            # exclude infill from the layers below if needed
+            # see discussion at https://github.com/alexrj/Slic3r/issues/240
+            # Update: do not exclude any infill. Sparse infill is able to absorb the excess material.
+            if (0) {
+                my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height;
+                for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) {
+                    Slic3r::debugf "  skipping infill below those areas at layer %d\n", $i;
+                    foreach my $lower_layerm (@{$self->get_layer($i)->regions}) {
+                        my @new_surfaces = ();
+                        # subtract the area from all types of surfaces
+                        foreach my $group (@{$lower_layerm->fill_surfaces->group}) {
+                            push @new_surfaces, map $group->[0]->clone(expolygon => $_),
+                                @{diff_ex(
+                                    [ map $_->p, @$group ],
+                                    [ map @$_, @$to_overextrude ],
+                                )};
+                            push @new_surfaces, map Slic3r::Surface->new(
+                                expolygon       => $_,
+                                surface_type    => S_TYPE_INTERNALVOID,
+                            ), @{intersection_ex(
+                                [ map $_->p, @$group ],
+                                [ map @$_, @$to_overextrude ],
+                            )};
+                        }
+                        $lower_layerm->fill_surfaces->clear;
+                        $lower_layerm->fill_surfaces->append($_) for @new_surfaces;
+                    }
+                    
+                    $excess -= $self->get_layer($i)->height;
+                }
+            }
+            */
+
+#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
+            layerm->export_region_slices_to_svg_debug("7_overextrude_over_bridge");
+            layerm->export_region_fill_surfaces_to_svg_debug("7_overextrude_over_bridge");
+#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
+        }
+    }
+}
+
+
 SlicingParameters PrintObject::slicing_parameters() const
 {
     return SlicingParameters::create_from_config(
@@ -1699,8 +1905,8 @@ void PrintObject::discover_horizontal_shells()
                     continue;
 //                Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
                 
-                size_t solid_layers = (type == stTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;                
-                for (int n = (type == stTop) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop) ? -- n : ++ n) {
+                size_t solid_layers = (type == stTop || type == stTopOverBridge) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;                
+                for (int n = (type == stTop || type == stTopOverBridge) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop || type == stTopOverBridge) ? -- n : ++ n) {
                     if (n < 0 || n >= int(this->layers.size()))
                         continue;
 //                    Slic3r::debugf "  looking for neighbors on layer %d...\n", $n;                  

Some files were not shown because too many files changed in this diff