diff --git a/xs/src/libslic3r/Fill/Fill.cpp b/xs/src/libslic3r/Fill/Fill.cpp index 7ab8a1da4..d9c1a594a 100644 --- a/xs/src/libslic3r/Fill/Fill.cpp +++ b/xs/src/libslic3r/Fill/Fill.cpp @@ -164,8 +164,15 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) fill_pattern = (surface.is_external() && ! is_bridge) ? (surface.is_top() ? layerm.region()->config.top_fill_pattern.value : layerm.region()->config.bottom_fill_pattern.value) : ipRectilinear; - } else if (density <= 0) - continue; + } else { + if (layerm.region()->config.infill_dense_layers.getInt() > 0 + && surface.maxNbLayersOnTop < layerm.region()->config.infill_dense_layers.getInt() + layerm.region()->config.top_solid_layers.getInt() + && surface.maxNbLayersOnTop >= layerm.region()->config.top_solid_layers.getInt()){ + density = layerm.region()->config.infill_dense_density.getFloat(); + } + if (density <= 0) + continue; + } // get filler object std::unique_ptr f = std::unique_ptr(Fill::new_from_type(fill_pattern)); @@ -222,15 +229,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) // Used by the concentric infill pattern to clip the loops to create extrusion paths. f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER; // f->layer_height = h; - //give the overlap size, it's not the real value (it can depend of the external_perimeter_extrusion_width) - f->overlap = layerm.region()->config.infill_overlap.get_abs_value(flow.nozzle_diameter); + //give the overlap size, it's not the real value (it can depend of the external_perimeter_extrusion_width) + f->overlap = layerm.region()->config.infill_overlap.get_abs_value(flow.nozzle_diameter); // apply half spacing using this flow's own spacing and generate infill FillParams params; params.density = 0.01 * density; params.dont_adjust = false; params.fill_exactly = layerm.region()->config.enforce_full_fill_volume.getBool(); - // calculate actual flow from spacing (which might have been adjusted by the infill // pattern generator) if (using_internal_flow) { @@ -240,12 +246,12 @@ 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()){ - params.flow_mult = layerm.region()->config.over_bridge_flow_ratio; - } - + + float flow_percent = 1; + if(surface.is_overBridge()){ + params.flow_mult = layerm.region()->config.over_bridge_flow_ratio; + } + f->fill_surface_extrusion(&surface, params, flow, out); } diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 64bd0517f..3e9a5ce68 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -205,6 +205,7 @@ public: void _make_perimeters(); void _infill(); void clip_fill_surfaces(); + void count_distance_top(); void discover_horizontal_shells(); void combine_infill(); void _generate_support_material(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 01f1a97bf..2c12c163e 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -827,6 +827,53 @@ PrintConfigDef::PrintConfigDef() def->min = 1; def->default_value = new ConfigOptionInt(1); + def = this->add("infill_dense_layers", coInt); + def->label = L("Number of dense layers"); + def->category = L("Infill"); + def->tooltip = L("Set the number of denser infill layer you want between the normal sparse infill and the top layers. 0 to disable"); + def->sidetext = L("layers"); + def->cli = "infill-dense-layers=i"; + def->min = 0; + def->default_value = new ConfigOptionInt(0); + + def = this->add("infill_dense_density", coPercent); + def->gui_type = "f_enum_open"; + def->gui_flags = "show_value"; + def->label = L("Dense fill density"); + def->category = L("Infill"); + def->tooltip = L("Density of the dense internal infill, expressed in the range 0% - 100%."); + def->sidetext = L("%"); + def->cli = "infill-dense-density=s"; + def->min = 0; + def->max = 100; + def->enum_values.push_back("0"); + def->enum_values.push_back("4"); + def->enum_values.push_back("5.5"); + def->enum_values.push_back("7.5"); + def->enum_values.push_back("10"); + def->enum_values.push_back("13"); + def->enum_values.push_back("18"); + def->enum_values.push_back("23"); + def->enum_values.push_back("31"); + def->enum_values.push_back("42"); + def->enum_values.push_back("55"); + def->enum_values.push_back("75"); + def->enum_values.push_back("100"); + def->enum_labels.push_back("0"); + def->enum_labels.push_back("4"); + def->enum_labels.push_back("5.5"); + def->enum_labels.push_back("7.5"); + def->enum_labels.push_back("10"); + def->enum_labels.push_back("13"); + def->enum_labels.push_back("18"); + def->enum_labels.push_back("23"); + def->enum_labels.push_back("31"); + def->enum_labels.push_back("42"); + def->enum_labels.push_back("55"); + def->enum_labels.push_back("75"); + def->enum_labels.push_back("100"); + def->default_value = new ConfigOptionPercent(42); + def = this->add("infill_extruder", coInt); def->label = L("Infill extruder"); def->category = L("Extruders"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index f69b806d3..b7b356f9a 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -29,7 +29,7 @@ enum GCodeFlavor { enum InfillPattern { ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, - ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSmooth, ipSmoothHilbert, ipSmoothTriple, + ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSmooth, ipSmoothHilbert, ipSmoothTriple, }; enum SupportMaterialPattern { @@ -242,12 +242,12 @@ protected: m_defaults = defaults; m_keys.clear(); m_keys.reserve(m_map_name_to_offset.size()); - for (const auto &kvp : defs->options) { - // Find the option given the option name kvp.first by an offset from (char*)m_defaults. - ConfigOption *opt = this->optptr(kvp.first, m_defaults); - if (opt == nullptr) - // This option is not defined by the ConfigBase of type T. - continue; + for (const auto &kvp : defs->options) { + // Find the option given the option name kvp.first by an offset from (char*)m_defaults. + ConfigOption *opt = this->optptr(kvp.first, m_defaults); + if (opt == nullptr) + // This option is not defined by the ConfigBase of type T. + continue; m_keys.emplace_back(kvp.first); const ConfigOptionDef *def = defs->get(kvp.first); assert(def != nullptr); @@ -392,7 +392,7 @@ public: ConfigOptionEnum top_fill_pattern; ConfigOptionEnum bottom_fill_pattern; ConfigOptionBool enforce_full_fill_volume; - ConfigOptionFloat external_infill_margin; + ConfigOptionFloat external_infill_margin; ConfigOptionFloatOrPercent external_perimeter_extrusion_width; ConfigOptionFloatOrPercent external_perimeter_speed; ConfigOptionBool external_perimeters_first; @@ -407,6 +407,8 @@ public: ConfigOptionInt infill_every_layers; ConfigOptionFloatOrPercent infill_overlap; ConfigOptionFloat infill_speed; + ConfigOptionInt infill_dense_layers; + ConfigOptionPercent infill_dense_density; ConfigOptionBool overhangs; ConfigOptionInt perimeter_extruder; ConfigOptionFloatOrPercent perimeter_extrusion_width; @@ -450,6 +452,8 @@ protected: OPT_PTR(infill_every_layers); OPT_PTR(infill_overlap); OPT_PTR(infill_speed); + OPT_PTR(infill_dense_layers); + OPT_PTR(infill_dense_density); OPT_PTR(overhangs); OPT_PTR(perimeter_extruder); OPT_PTR(perimeter_extrusion_width); @@ -753,7 +757,7 @@ class FullPrintConfig : public HostConfig { STATIC_PRINT_CONFIG_CACHE_DERIVED(FullPrintConfig) - FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) { initialize_cache(); *this = s_cache_FullPrintConfig.defaults(); } + FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0), HostConfig(0) { initialize_cache(); *this = s_cache_FullPrintConfig.defaults(); } public: // Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned. diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 938fff712..aba4736b2 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -156,9 +156,9 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorreset_layer_height_profile(); - } - else if ( + this->reset_layer_height_profile(); + } + else if ( opt_key == "clip_multipart_objects" || opt_key == "elefant_foot_compensation" || opt_key == "support_material_contact_distance" @@ -189,10 +189,12 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorreset_layer_height_profile(); - this->invalidate_all_steps(); + this->reset_layer_height_profile(); + this->invalidate_all_steps(); invalidated = true; } } @@ -366,15 +368,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(); - this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stInternalBridge); - this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stBottomBridge); - this->replaceSurfaceType( stTop, stTopOverBridge, stInternalBridge); - this->replaceSurfaceType( stTop, stTopOverBridge, stBottomBridge); + this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stInternalBridge); + this->replaceSurfaceType( stInternalSolid, stInternalOverBridge, stBottomBridge); + this->replaceSurfaceType( stTop, stTopOverBridge, stInternalBridge); + this->replaceSurfaceType( stTop, stTopOverBridge, stBottomBridge); // combine fill surfaces to honor the "infill every N layers" option this->combine_infill(); - + // count the distance from the nearest top surface, to allow to use denser infill + // if neded and if infill_dense_layers is positive. + this->count_distance_top(); + #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) { @@ -390,6 +395,38 @@ void PrintObject::_prepare_infill() #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ } +void PrintObject::count_distance_top(){ + + for (int idx_region = 0; idx_region < this->_print->regions.size(); ++idx_region) { + + //count how many surface there are on each one + LayerRegion *previousOne = NULL; + if (this->layers.size() > 1) previousOne = this->layers[this->layers.size() - 1]->get_region(idx_region); + if (previousOne != NULL && previousOne->region()->config.infill_dense_layers.getInt() > 0){ + for (int idx_layer = this->layers.size() - 2; idx_layer >= 0; --idx_layer){ + LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region); + for (Surface &surf : layerm->fill_surfaces.surfaces){ + if (!surf.is_top()){ + surf.maxNbLayersOnTop = 65000; + //find the surface which intersect with the smalle maxNb possible + for (Surface &upp : previousOne->fill_surfaces.surfaces){ + // i'm using that because the result is better & different than + // upp.expolygon.overlaps(surf.expolygon), surf.expolygon.overlaps(upp.expolygon) + if (intersection_ex(surf, upp).size() > 0){ + surf.maxNbLayersOnTop = std::min(surf.maxNbLayersOnTop, (unsigned short)(upp.maxNbLayersOnTop + 1)); + } + } + }else{ + surf.maxNbLayersOnTop = 0; + } + } + previousOne = layerm; + } + } + } + +} + // This function analyzes slices of a region (SurfaceCollection slices). // Each region slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface. // Initially all slices are of type stInternal. @@ -487,7 +524,6 @@ 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) { @@ -504,7 +540,6 @@ 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 @@ -512,22 +547,6 @@ 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<slices.expolygons.size()<<" > "<slices.expolygons.size();i++) std::cout<<" area of under_lower_layer "<slices.expolygons[i].area()<<"\n"; - // for(int i=0;ilayers[idx_layer]; @@ -811,13 +824,13 @@ void PrintObject::discover_vertical_shells() #if 0 // #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { - Slic3r::SVG svg_cummulative(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d.svg", debug_idx), this->bounding_box()); + Slic3r::SVG svg_cummulative(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d.svg", debug_idx), this->bounding_box()); for (int n = (int)idx_layer - n_extra_bottom_layers; n <= (int)idx_layer + n_extra_top_layers; ++ n) { if (n < 0 || n >= (int)this->layers.size()) continue; ExPolygons &expolys = this->layers[n]->perimeter_expolygons; for (size_t i = 0; i < expolys.size(); ++ i) { - Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d-layer%d-expoly%d.svg", debug_idx, n, i), get_extents(expolys[i])); + Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-run%d-layer%d-expoly%d.svg", debug_idx, n, i), get_extents(expolys[i])); svg.draw(expolys[i]); svg.draw_outline(expolys[i].contour, "black", scale_(0.05)); svg.draw_outline(expolys[i].holes, "blue", scale_(0.05)); @@ -857,7 +870,7 @@ void PrintObject::discover_vertical_shells() } #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { - Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-%d.svg", debug_idx), get_extents(shell)); + Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-%d.svg", debug_idx), get_extents(shell)); svg.draw(shell); svg.draw_outline(shell, "black", scale_(0.05)); svg.Close(); @@ -984,8 +997,8 @@ void PrintObject::discover_vertical_shells() #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal-%d.svg", debug_idx), get_extents(shell), new_internal, "black", "blue", scale_(0.05)); - SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_void-%d.svg", debug_idx), get_extents(shell), new_internal_void, "black", "blue", scale_(0.05)); - SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_solid-%d.svg", debug_idx), get_extents(shell), new_internal_solid, "black", "blue", scale_(0.05)); + SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_void-%d.svg", debug_idx), get_extents(shell), new_internal_void, "black", "blue", scale_(0.05)); + SVG::export_expolygons(debug_out_path("discover_vertical_shells-new_internal_solid-%d.svg", debug_idx), get_extents(shell), new_internal_solid, "black", "blue", scale_(0.05)); } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ @@ -1000,11 +1013,11 @@ void PrintObject::discover_vertical_shells() BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells for region " << idx_region << " in parallel - end"; #ifdef SLIC3R_DEBUG_SLICE_PROCESSING - for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++idx_layer) { - LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region); - layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-final"); - layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-final"); - } + for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++idx_layer) { + LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region); + layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells-final"); + layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells-final"); + } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ } // for each region @@ -1162,29 +1175,29 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r // 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; + + 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(); + double totoverareaInit=0; + for (ExPolygon &ex : union_ex(internal_over_tot_init)) totoverareaInit+=ex.area(); - Polygons stBottom_init; + 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(); + double bottomeareainit=0; + for (ExPolygon &ex : union_ex(stBottom_init)) bottomeareainit+=ex.area(); - Polygons stBottomBridge_init; + 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; + 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(); + double intbridgeareainit=0; + for (ExPolygon &ex : union_ex(stIntBridge_init)) intbridgeareainit+=ex.area(); // check whether the lower area is deep enough for absorbing the extra flow // (for obvious physical reasons but also for preventing the bridge extrudates @@ -1200,22 +1213,22 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r // 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; + 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(); + 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(); (*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(); - + } + double sumarea=0; + for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area(); + // intersect such lower internal surfaces with the candidate solid surfaces to_overextrude_pp = intersection(to_overextrude_pp, lower_internal); } @@ -1244,21 +1257,21 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r 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; + double overareafinal = 0, solidareafinal=0; for (ExPolygon &ex : to_overextrude){ - overareafinal += ex.area(); + 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; + 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(); - - /* + double totoverarea=0; + for (ExPolygon &ex : union_ex(internal_over_tot)) totoverarea+=ex.area(); + + /* # 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. @@ -1450,8 +1463,8 @@ void PrintObject::_slice() goto end; delete layer; this->layers.pop_back(); - if (! this->layers.empty()) - this->layers.back()->upper_layer = nullptr; + if (! this->layers.empty()) + this->layers.back()->upper_layer = nullptr; } end: ; @@ -1478,11 +1491,11 @@ end: // Multiple regions, growing, shrinking or just clipping one region by the other. // When clipping the regions, priority is given to the first regions. Polygons processed; - for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id) { + for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id) { LayerRegion *layerm = layer->regions[region_id]; - ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); - if (scale) - slices = offset_ex(slices, delta); + ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); + if (scale) + slices = offset_ex(slices, delta); if (region_id > 0 && clip) // Trim by the slices of already processed regions. slices = diff_ex(to_polygons(std::move(slices)), processed); @@ -1756,7 +1769,7 @@ void PrintObject::_infill() ### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers}; */ - this->state.set_done(posInfill); + this->state.set_done(posInfill); } // Only active if config->infill_only_where_needed. This step trims the sparse infill, @@ -2015,7 +2028,7 @@ void PrintObject::discover_horizontal_shells() // Use an existing surface as a template, it carries the bridge angle etc. *group.front()); } - EXTERNAL:; + EXTERNAL:; } // foreach type (stTop, stBottom, stBottomBridge) } // for each layer } // for each region @@ -2076,12 +2089,12 @@ void PrintObject::combine_infill() // loop through layers to which we have assigned layers to combine for (size_t layer_idx = 0; layer_idx < this->layers.size(); ++ layer_idx) { size_t num_layers = combine[layer_idx]; - if (num_layers <= 1) + if (num_layers <= 1) continue; // Get all the LayerRegion objects to be combined. std::vector layerms; layerms.reserve(num_layers); - for (size_t i = layer_idx + 1 - num_layers; i <= layer_idx; ++ i) + for (size_t i = layer_idx + 1 - num_layers; i <= layer_idx; ++ i) layerms.emplace_back(this->layers[i]->regions[region_id]); // We need to perform a multi-layer intersection, so let's split it in pairs. // Initialize the intersection with the candidates of the lowest layer. @@ -2151,7 +2164,7 @@ void PrintObject::reset_layer_height_profile() { // Reset the layer_heigth_profile. this->layer_height_profile.clear(); - this->layer_height_profile_valid = false; + this->layer_height_profile_valid = false; // Reset the source layer_height_profile if it exists at the ModelObject. this->model_object()->layer_height_profile.clear(); this->model_object()->layer_height_profile_valid = false; diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 3ad7380cd..252a470c1 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -41,35 +41,42 @@ public: unsigned short thickness_layers; // in layers double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined) unsigned short extra_perimeters; + unsigned short maxNbLayersOnTop; Surface(const Slic3r::Surface &rhs) : surface_type(rhs.surface_type), expolygon(rhs.expolygon), thickness(rhs.thickness), thickness_layers(rhs.thickness_layers), - bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters) + bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters), + maxNbLayersOnTop(rhs.maxNbLayersOnTop) {}; Surface(SurfaceType _surface_type, const ExPolygon &_expolygon) : surface_type(_surface_type), expolygon(_expolygon), - thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0) + thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0), + maxNbLayersOnTop(0) {}; Surface(const Surface &other, const ExPolygon &_expolygon) : surface_type(other.surface_type), expolygon(_expolygon), thickness(other.thickness), thickness_layers(other.thickness_layers), - bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters) + bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters), + maxNbLayersOnTop(other.maxNbLayersOnTop) {}; Surface(Surface &&rhs) : surface_type(rhs.surface_type), expolygon(std::move(rhs.expolygon)), thickness(rhs.thickness), thickness_layers(rhs.thickness_layers), - bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters) + bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters), + maxNbLayersOnTop(rhs.maxNbLayersOnTop) {}; Surface(SurfaceType _surface_type, const ExPolygon &&_expolygon) : surface_type(_surface_type), expolygon(std::move(_expolygon)), - thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0) + thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0), + maxNbLayersOnTop(0) {}; Surface(const Surface &other, const ExPolygon &&_expolygon) : surface_type(other.surface_type), expolygon(std::move(_expolygon)), thickness(other.thickness), thickness_layers(other.thickness_layers), - bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters) + bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters), + maxNbLayersOnTop(other.maxNbLayersOnTop) {}; Surface& operator=(const Surface &rhs) @@ -80,6 +87,7 @@ public: thickness_layers = rhs.thickness_layers; bridge_angle = rhs.bridge_angle; extra_perimeters = rhs.extra_perimeters; + maxNbLayersOnTop = rhs.maxNbLayersOnTop; return *this; } @@ -91,6 +99,7 @@ public: thickness_layers = rhs.thickness_layers; bridge_angle = rhs.bridge_angle; extra_perimeters = rhs.extra_perimeters; + maxNbLayersOnTop = rhs.maxNbLayersOnTop; return *this; } @@ -104,7 +113,7 @@ public: bool is_internal() const; bool is_bottom() const; bool is_bridge() const; - bool is_overBridge() const; + bool is_overBridge() const; }; typedef std::vector Surfaces; @@ -151,12 +160,12 @@ inline ExPolygons to_expolygons(const Surfaces &src) inline ExPolygons to_expolygons(Surfaces &&src) { - ExPolygons expolygons; - expolygons.reserve(src.size()); - for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it) - expolygons.emplace_back(ExPolygon(std::move(it->expolygon))); - src.clear(); - return expolygons; + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.emplace_back(ExPolygon(std::move(it->expolygon))); + src.clear(); + return expolygons; } inline ExPolygons to_expolygons(const SurfacesPtr &src) diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 33af8fa3e..985d7f28d 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -297,9 +297,10 @@ const std::vector& Preset::print_options() "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "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", - "over_bridge_flow_ratio", "clip_multipart_objects", "enforce_full_fill_volume", "external_infill_margin", + "over_bridge_flow_ratio", "clip_multipart_objects", "enforce_full_fill_volume", "external_infill_margin", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", - "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "only_one_perimeter_top", "compatible_printers", "compatible_printers_condition","inherits" + "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "only_one_perimeter_top", "compatible_printers", + "compatible_printers_condition", "inherits", "infill_dense_layers", "infill_dense_density" }; return s_opts; } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 0d9301e76..10d752145 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -856,6 +856,10 @@ void TabPrint::build() optgroup = page->new_optgroup(_(L("Reducing printing time"))); optgroup->append_single_option_line("infill_every_layers"); optgroup->append_single_option_line("infill_only_where_needed"); + line = { _(L("Use denser infill below top layers")), "" }; + line.append_option(optgroup->get_option("infill_dense_layers")); + line.append_option(optgroup->get_option("infill_dense_density")); + optgroup->append_line(line); optgroup = page->new_optgroup(_(L("Advanced"))); optgroup->append_single_option_line("solid_infill_every_layers");