Browse Source

Add "one perimeter for top surface" & more
Change the top smooth infill to be better on small surfaces (no over extrusion)
add a bit of overlap for smooth (hope there are at least 1 perimeter, i can check it but i have to pass the parameter object in the config, and nobody do that right?)

remi 7 years ago
parent
commit
506ebc0e77

+ 1 - 0
lib/Slic3r/GUI/Tab.pm

@@ -599,6 +599,7 @@ sub build {
         {
             my $optgroup = $page->new_optgroup('Quality (slower slicing)');
             $optgroup->append_single_option_line('extra_perimeters');
+            $optgroup->append_single_option_line('only_one_perimeter_top');
             $optgroup->append_single_option_line('ensure_vertical_shell_thickness');
             $optgroup->append_single_option_line('avoid_crossing_perimeters');
             $optgroup->append_single_option_line('thin_walls');

+ 90 - 36
xs/src/libslic3r/Fill/FillRectilinear2.cpp

@@ -1488,44 +1488,98 @@ void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams
     params2.density *= 2.0f;
     Polylines polylines_out;
     Polylines polylines_outNoExtrud;
-    if (! fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out) ||
-        ! fill_surface_by_lines(surface, params2, float(M_PI/2), 0.f, polylines_outNoExtrud)) {
-        printf("FillSmooth::fill_surface() failed to fill a region.\n");
-    } 
-	
-	if (polylines_out.empty())
-		return;
-	
-	// Flow tempFlow = flow;
-	
-	ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
-	out.entities.push_back(eecroot);
-	eecroot->no_sort = true;
 	
-	// float stdflowWidth = tempFlow.width;
-	// Save into layer.
-	ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
-	eecroot->entities.push_back(eec);
-	eec->no_sort = true;
-	// print at almost 100% (90%) flow
-	extrusion_entities_append_paths(
-		eec->entities, STDMOVE(polylines_out),
-		flow.bridge ?
-			erBridgeInfill :
-			(surface->is_solid() ?
-				((surface->surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
-				erInternalInfill),
-		flow.mm3_per_mm()*0.9, flow.width*0.9, flow.height);
+	//choose between v1 (no extrusion on second pass) and v2 (small extrusion on second pass)
+	if(surface->area() < (scale_(this->spacing)*scale_(this->spacing)) * 100){
+		//v1 (only if < 100 nozzle² (for a 0.4 nozzle, it's 16 mm² ~ 0.16 cm² ~ half of a 5mmx5mm cube on a notebook)
+		Surface surfaceIncr(*surface);
+		Polygons paths = offset(surfaceIncr.expolygon.contour, scale_(this->spacing));
+		surfaceIncr.expolygon.contour = paths[0];
+		
+		if (! fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out) ||
+			! fill_surface_by_lines(&surfaceIncr, params2, float(M_PI/2), 0.f, polylines_outNoExtrud)) {
+			printf("FillSmooth::fill_surface() failed to fill a region.\n");
+		} 
+		
+		if (polylines_out.empty())
+			return;
+		
+		// Flow tempFlow = flow;
 		
-	// Save into layer smoothing path.
-	eec = new ExtrusionEntityCollection();
-	eecroot->entities.push_back(eec);
-	eec->no_sort = true;
-	//print the last 10% with 2*15% -> gapfill (if less => gaps)
-	extrusion_entities_append_paths(
-		eec->entities, STDMOVE(polylines_outNoExtrud),
-		erInternalInfill, //speedy (it's generally the most speedy)
-		flow.mm3_per_mm()*0.15, flow.width*0.15, flow.height);
+		ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
+		out.entities.push_back(eecroot);
+		eecroot->no_sort = true;
+		
+		// float stdflowWidth = tempFlow.width;
+		// Save into layer.
+		ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
+		eecroot->entities.push_back(eec);
+		eec->no_sort = true;
+		// print at almost 100% (90%) flow
+		extrusion_entities_append_paths(
+			eec->entities, STDMOVE(polylines_out),
+			flow.bridge ?
+				erBridgeInfill :
+				(surface->is_solid() ?
+					((surface->surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
+					erInternalInfill),
+			flow.mm3_per_mm()*1, flow.width*1, flow.height);
+			
+		// Save into layer smoothing path.
+		eec = new ExtrusionEntityCollection();
+		eecroot->entities.push_back(eec);
+		eec->no_sort = true;
+		//print the last 10% with 2*15% -> gapfill (if less => gaps)
+		extrusion_entities_append_paths(
+			eec->entities, STDMOVE(polylines_outNoExtrud),
+			erInternalInfill, //speedy (it's generally the most speedy)
+			0.f, flow.width*0.05, flow.height);
+	}else{
+		//v2
+		Surface surfaceIncr(*surface);
+		Polygons paths = offset(surfaceIncr.expolygon.contour, scale_(this->spacing * 0.3f));
+		surfaceIncr.expolygon.contour = paths[0];
+		
+		if (! fill_surface_by_lines(surface, params, 0.f, 0.f, polylines_out) ||
+			! fill_surface_by_lines(&surfaceIncr, params2, float(M_PI/2), 0.f, polylines_outNoExtrud)) {
+			printf("FillSmooth::fill_surface() failed to fill a region.\n");
+		} 
+		
+		if (polylines_out.empty())
+			return;
+		
+		// Flow tempFlow = flow;
+		
+		ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
+		out.entities.push_back(eecroot);
+		eecroot->no_sort = true;
+		
+		// float stdflowWidth = tempFlow.width;
+		// Save into layer.
+		ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
+		eecroot->entities.push_back(eec);
+		eec->no_sort = true;
+		// print at almost 100% (90%) flow
+		extrusion_entities_append_paths(
+			eec->entities, STDMOVE(polylines_out),
+			flow.bridge ?
+				erBridgeInfill :
+				(surface->is_solid() ?
+					((surface->surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
+					erInternalInfill),
+			flow.mm3_per_mm()*0.9, flow.width*0.9, flow.height);
+			
+		// Save into layer smoothing path.
+		eec = new ExtrusionEntityCollection();
+		eecroot->entities.push_back(eec);
+		eec->no_sort = true;
+		//print the last 10% with 2*15% -> gapfill (if less => gaps)
+		extrusion_entities_append_paths(
+			eec->entities, STDMOVE(polylines_outNoExtrud),
+			erInternalInfill, //speedy (it's generally the most speedy)
+			flow.mm3_per_mm()*0.15, flow.width*0.15, flow.height);
+	}
+	
 }
 
 } // namespace Slic3r

+ 4 - 2
xs/src/libslic3r/PerimeterGenerator.cpp

@@ -53,8 +53,10 @@ PerimeterGenerator::process()
     // extra perimeters for each one
     for (const Surface &surface : this->slices->surfaces) {
         // detect how many perimeters must be generated for this island
-        const int loop_number = this->config->perimeters + surface.extra_perimeters -1;  // 0-indexed loops
-        
+        const int loop_number =  (config->only_one_perimeter_top && surface.is_external() && !surface.is_bridge() && surface.surface_type == stTop) ? 
+			0 : // only 1 perimeter for top surface if the option is set (0-indexed loops)
+			(this->config->perimeters + surface.extra_perimeters -1);  // normal case (0-indexed loops)
+		
         Polygons gaps;
         
         Polygons last = surface.expolygon.simplify_p(SCALED_RESOLUTION);

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

@@ -299,6 +299,14 @@ PrintConfigDef::PrintConfigDef()
                    "is supported.";
     def->cli = "extra-perimeters!";
     def->default_value = new ConfigOptionBool(true);
+	
+    def = this->add("only_one_perimeter_top", coBool);
+    def->label = "Only one perimeter on Top surfaces";
+    def->category = "Layers and Perimeters";
+    def->tooltip = "Use only one perimeter on flat top surface, to let more space to the top infill pattern.";
+    def->cli = "one-top-perimeters!";
+    def->default_value = new ConfigOptionBool(true);
+
 
     def = this->add("extruder", coInt);
     def->gui_type = "i_enum_open";

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

@@ -382,6 +382,7 @@ public:
     ConfigOptionFloatOrPercent      external_perimeter_speed;
     ConfigOptionBool                external_perimeters_first;
     ConfigOptionBool                extra_perimeters;
+    ConfigOptionBool                only_one_perimeter_top;
     ConfigOptionFloat               fill_angle;
     ConfigOptionPercent             fill_density;
     ConfigOptionEnum<InfillPattern> fill_pattern;
@@ -420,6 +421,7 @@ protected:
         OPT_PTR(external_perimeter_speed);
         OPT_PTR(external_perimeters_first);
         OPT_PTR(extra_perimeters);
+        OPT_PTR(only_one_perimeter_top);
         OPT_PTR(fill_angle);
         OPT_PTR(fill_density);
         OPT_PTR(fill_pattern);

+ 12 - 0
xs/src/libslic3r/PrintObject.cpp

@@ -1437,6 +1437,8 @@ void PrintObject::_make_perimeters()
 {
     if (this->state.is_done(posPerimeters)) return;
     this->state.set_started(posPerimeters);
+	
+	
 
     BOOST_LOG_TRIVIAL(info) << "Generating perimeters...";
     
@@ -1447,6 +1449,16 @@ void PrintObject::_make_perimeters()
         this->typed_slices = false;
         this->state.invalidate(posPrepareInfill);
     }
+	
+	//if we want only one perimeter for each top surface, we need to know who is a top surface before the infill
+	// ! detect_surfaces_type is done is every case in the infill() call chain.
+	if(_print->default_region_config.only_one_perimeter_top){
+		// This will assign a type (top/bottom/internal) to $layerm->slices.
+		// Then the classifcation of $layerm->slices is transfered onto 
+		// the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
+		// by the cummulative area of the previous $layerm->fill_surfaces.
+		this->detect_surfaces_type();
+	}
     
     // compare each layer to the one below, and mark those slices needing
     // one additional inner perimeter, like the top of domed objects-

+ 1 - 1
xs/src/slic3r/GUI/Preset.cpp

@@ -199,7 +199,7 @@ const std::vector<std::string>& Preset::print_options()
         "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", 
         "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", 
         "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
-        "wipe_tower_width", "wipe_tower_per_color_wipe",
+        "wipe_tower_width", "wipe_tower_per_color_wipe", "only_one_perimeter_top", 
         "compatible_printers", "compatible_printers_condition"
     };
     return s_opts;