diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 083f8c13f..b53751454 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -54,16 +54,18 @@ group:Advanced setting:seam_position setting:seam_travel end_line - line:External Perimeter - setting:external_perimeters_first - setting:external_perimeters_vase - setting:external_perimeters_nothole - setting:external_perimeters_hole - end_line line:Looping perimeter setting:perimeter_loop setting:perimeter_loop_seam end_line +group: External perimeter first + setting:label$Activate:external_perimeters_first + line:Apply on + setting:external_perimeters_nothole + setting:external_perimeters_hole + end_line + setting:external_perimeters_vase + setting:perimeter_bonding page:Slicing:layers group:Layer height @@ -230,9 +232,12 @@ group:Extrusion width setting:top_infill_extrusion_width setting:support_material_extrusion_width group:Overlap + line:Perimeter overlap + setting:label$External:external_perimeter_overlap + setting:label$Inner:perimeter_overlap + end_line setting:infill_overlap setting:bridge_overlap - setting:external_perimeter_overlap group:Flow line:Flow ratio setting:bridge_flow_ratio diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index b9e788418..0243ecf09 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -172,7 +172,7 @@ float Flow::spacing() const float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI); float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing); #else - float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI))); + float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI) * spacing_ratio)); #endif // assert(res > 0.f); if (res <= 0.f) diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp index 448d5d220..f22accaee 100644 --- a/src/libslic3r/Flow.hpp +++ b/src/libslic3r/Flow.hpp @@ -65,6 +65,8 @@ public: float nozzle_diameter; // Is it a bridge? bool bridge; + // % of spacing taken into account 1=>all/default, 0=> width=spacing + float spacing_ratio = 1; Flow(float _w, float _h, float _nd, bool _bridge = false) : width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {} diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 067f333bf..5f60cfa8c 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -37,6 +37,10 @@ namespace Slic3r { void PerimeterGenerator::process() { + //set spacing + this->perimeter_flow.spacing_ratio = this->object_config->perimeter_overlap.get_abs_value(1); + this->ext_perimeter_flow.spacing_ratio = this->object_config->external_perimeter_overlap.get_abs_value(1); + // other perimeters this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm(); coord_t perimeter_width = this->perimeter_flow.scaled_width(); @@ -50,22 +54,30 @@ void PerimeterGenerator::process() coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing(); //spacing between external perimeter and the second coord_t ext_perimeter_spacing2 = this->ext_perimeter_flow.scaled_spacing(this->perimeter_flow); - //external_perimeter_overlap effect: change distance between the extrenal periemter and the other ones. - if (this->config->external_perimeter_overlap.get_abs_value(1) != 1) { - //choose between the normal spacing and "don't touch it". - ext_perimeter_spacing2 = - ext_perimeter_spacing2 * this->config->external_perimeter_overlap.get_abs_value(1) - + (ext_perimeter_width + perimeter_width) * 0.5f * (1 - this->config->external_perimeter_overlap.get_abs_value(1)); - } - + // overhang perimeters - this->_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm(); - + this->_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm(); + // solid infill - coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing(); + coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing(); + + //infill / perimeter + coord_t infill_peri_overlap = (coord_t)scale_(this->config->get_abs_value("infill_overlap", unscale(perimeter_spacing + solid_infill_spacing) / 2)); + // infill gap to add vs periemter (useful if using perimeter bonding) + coord_t infill_gap = 0; + // nozzle diameter const double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1); + + // perimeter conding set. + if (this->perimeter_flow.spacing_ratio == 1 + && this->ext_perimeter_flow.spacing_ratio == 1 + && this->config->external_perimeters_first + && this->object_config->perimeter_bonding.value > 0) { + infill_gap = (1 - this->object_config->perimeter_bonding.get_abs_value(1)) * ext_perimeter_spacing; + ext_perimeter_spacing2 -= infill_gap; + } // Calculate the minimum required spacing between two adjacent traces. // This should be equal to the nominal flow spacing but we experiment @@ -88,7 +100,7 @@ void PerimeterGenerator::process() this->_lower_slices_p = offset(*this->lower_slices, double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter)))); } - // have to grown the periemters if mill post-process + // have to grown the perimeters if mill post-process MillingPostProcess miller(this->slices, this->lower_slices, config, object_config, print_config); bool have_to_grow_for_miller = miller.can_be_milled(layer) && config->milling_extra_size.get_abs_value(1) > 0; ExPolygons unmillable; @@ -218,7 +230,6 @@ void PerimeterGenerator::process() //it's not dangerous as it will be intersected by 'unsupported' later //FIXME: add overlap in this->fill_surfaces->append //FIXME: it overlap inside unsuppported not-bridgeable area! - double overlap = scale_(this->config->get_abs_value("infill_overlap", unscale(perimeter_spacing))); //bridgeable_simplified = offset2_ex(bridgeable_simplified, (double)-perimeter_spacing, (double)perimeter_spacing * 2); //ExPolygons unbridgeable = offset_ex(diff_ex(unsupported, bridgeable_simplified), perimeter_spacing * 3 / 2); @@ -391,7 +402,7 @@ void PerimeterGenerator::process() if ( this->config->extra_perimeters_overhangs && !last.empty() && !overhangs_unsupported.empty()) { overhangs_unsupported = intersection_ex(overhangs_unsupported, last, true); if (overhangs_unsupported.size() > 0) { - //please don't stop adding periemter yet. + //please don't stop adding perimeter yet. has_overhang = true; } } @@ -456,9 +467,9 @@ void PerimeterGenerator::process() ExPolygons thin = offset_ex(half_thin, double(min_width / 2)); assert(thin.size() <= 1); if (thin.empty()) continue; - coord_t overlap = (coord_t)scale_(this->config->thin_walls_overlap.get_abs_value(this->ext_perimeter_flow.nozzle_diameter)); + coord_t thin_walls_overlap = (coord_t)scale_(this->config->thin_walls_overlap.get_abs_value(this->ext_perimeter_flow.nozzle_diameter)); ExPolygons anchor = intersection_ex(offset_ex(half_thin, double(min_width / 2) + - (float)(overlap), jtSquare), no_thin_zone, true); + (float)(thin_walls_overlap), jtSquare), no_thin_zone, true); ExPolygons bounds = union_ex(thin, anchor, true); for (ExPolygon &bound : bounds) { if (!intersection_ex(thin[0], bound).empty()) { @@ -472,7 +483,7 @@ void PerimeterGenerator::process() min_width, coord_t(this->layer->height) }; ma.use_bounds(bound) .use_min_real_width((coord_t)scale_(this->ext_perimeter_flow.nozzle_diameter)) - .use_tapers(overlap) + .use_tapers(thin_walls_overlap) .build(thin_walls); } break; @@ -818,7 +829,7 @@ void PerimeterGenerator::process() last = diff_ex(to_polygons(last), gap_fill.polygons_covered_by_width(10.f)); } } - //TODO: if a gapfill extrusion is a loop and with width always >= periemter width then change the type to perimeter and put it at the right place in the loops vector. + //TODO: if a gapfill extrusion is a loop and with width always >= perimeter width then change the type to perimeter and put it at the right place in the loops vector. // create one more offset to be used as boundary for fill // we offset by half the perimeter spacing (to get to the actual infill boundary) @@ -832,9 +843,8 @@ void PerimeterGenerator::process() // two or more loops? perimeter_spacing / 2; // only apply infill overlap if we actually have one perimeter - coord_t overlap = 0; - if (inset > 0) { - overlap = (coord_t)scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2))); + if (inset == 0) { + infill_peri_overlap = 0; } // simplify infill contours according to resolution Polygons not_filled_p; @@ -846,14 +856,14 @@ void PerimeterGenerator::process() // append infill areas to fill_surfaces //auto it_surf = this->fill_surfaces->surfaces.end(); ExPolygons infill_exp = offset2_ex(not_filled_exp, - -inset - min_perimeter_infill_spacing / 2 + overlap, + -inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap, (float)min_perimeter_infill_spacing / 2); this->fill_surfaces->append(infill_exp, stPosInternal | stDensSparse); - if (overlap != 0) { + if (infill_peri_overlap != 0) { ExPolygons polyWithoutOverlap = offset2_ex( not_filled_exp, - -inset - min_perimeter_infill_spacing / 2, + -inset - infill_gap - min_perimeter_infill_spacing / 2, (float) min_perimeter_infill_spacing / 2); this->fill_no_overlap.insert(this->fill_no_overlap.end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end()); } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 0c65ab3af..035411558 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -729,12 +729,45 @@ void PrintConfigDef::init_fff_params() def->label = L("external perimeter overlap"); def->full_label = L("Ext. peri. overlap"); def->category = OptionCategory::width; - def->tooltip = L("This perimeter allow you to reduce the overlap between the perimeters and the external one, to reduce the impact of the perimeters artifacts." + def->tooltip = L("This setting allow you to reduce the overlap between the perimeters and the external one, to reduce the impact of the perimeters artifacts." + " 100% means that no gaps is left, and 0% means that the external perimeter isn't contributing to the overlap with the 'inner' one." "\nIt's very experimental, please report about the usefulness. It may be removed if there is no use of it."); def->sidetext = L("%"); + def->min = 0; + def->max = 100; def->mode = comExpert; def->set_default_value(new ConfigOptionPercent(100)); + def = this->add("perimeter_overlap", coPercent); + def->label = L("perimeter overlap"); + def->full_label = L("Perimeter overlap"); + def->category = OptionCategory::width; + def->tooltip = L("This setting allow you to reduce the overlap between the perimeters, to reduce the impact of the perimeters artifacts." + " 100% means that no gaps is left, and 0% means that perimeters are not touching each other anymore." + "\nIt's very experimental, please report about the usefulness. It may be removed if there is no use for it."); + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionPercent(100)); + + def = this->add("perimeter_bonding", coPercent); + def->label = L("Better bonding"); + def->full_label = L("Perimeter bonding"); + def->category = OptionCategory::perimeter; + def->tooltip = L("This setting may degrad a bit the quality of your external perimeter, in exchange for a better bonding between perimeters." + "Use it if you have great difficulties with perimeter bonding, for example with high temperature filaments." + "\nThis percentage is the % of overlap between perimeters, a bit like perimeter_overlap and external_perimeter_overlap, but in reverse." + " You have to set perimeter_overlap and external_perimeter_overlap to 100%, or this setting has no effect." + " 0: no effect, 50%: half of the nozzle will be over an already extruded perimeter while extruding a new one" + ", unless it's an external ones)." + "\nIt's very experimental, please report about the usefulness. It may be removed if there is no use for it."); + def->sidetext = L("%"); + def->min = 0; + def->max = 50; + def->mode = comExpert; + def->set_default_value(new ConfigOptionPercent(0)); + def = this->add("external_perimeter_speed", coFloatOrPercent); def->label = L("External"); def->full_label = L("External perimeters speed"); @@ -2022,7 +2055,7 @@ void PrintConfigDef::init_fff_params() def->label = L("minimum top width for infill"); def->category = OptionCategory::speed; def->tooltip = L("If a top surface has to be printed and it's partially covered by an other layer, it won't be considered at a top layer where his width is below this value." - " This can be useful to not let the 'one perimeter on top' trigger on surface that should be covered only by periemters." + " This can be useful to not let the 'one perimeter on top' trigger on surface that should be covered only by perimeters." " This value can be a mm or a % of the perimeter extrusion width."); def->sidetext = L("mm or %"); def->ratio_over = "perimeter_extrusion_width"; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index d2dea2f51..8467e5481 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -494,6 +494,7 @@ public: ConfigOptionBool dont_support_bridges; ConfigOptionPercent external_perimeter_cut_corners; ConfigOptionBool exact_last_layer_height; + ConfigOptionPercent external_perimeter_overlap; ConfigOptionFloatOrPercent extrusion_width; ConfigOptionFloatOrPercent first_layer_height; ConfigOptionFloat first_layer_size_compensation; @@ -503,6 +504,8 @@ public: ConfigOptionBool interface_shells; ConfigOptionFloat layer_height; ConfigOptionFloat model_precision; + ConfigOptionPercent perimeter_bonding; + ConfigOptionPercent perimeter_overlap; ConfigOptionInt raft_layers; ConfigOptionEnum seam_position; ConfigOptionBool seam_travel; @@ -555,6 +558,7 @@ protected: OPT_PTR(dont_support_bridges); OPT_PTR(external_perimeter_cut_corners); OPT_PTR(exact_last_layer_height); + OPT_PTR(external_perimeter_overlap); OPT_PTR(extrusion_width); OPT_PTR(hole_size_compensation); OPT_PTR(first_layer_height); @@ -563,6 +567,8 @@ protected: OPT_PTR(interface_shells); OPT_PTR(layer_height); OPT_PTR(model_precision); + OPT_PTR(perimeter_bonding); + OPT_PTR(perimeter_overlap); OPT_PTR(raft_layers); OPT_PTR(seam_position); OPT_PTR(seam_travel); @@ -621,7 +627,6 @@ public: ConfigOptionBool enforce_full_fill_volume; ConfigOptionFloatOrPercent external_infill_margin; ConfigOptionFloatOrPercent external_perimeter_extrusion_width; - ConfigOptionPercent external_perimeter_overlap; ConfigOptionFloatOrPercent external_perimeter_speed; ConfigOptionBool external_perimeters_first; ConfigOptionBool external_perimeters_vase; @@ -709,7 +714,6 @@ protected: OPT_PTR(enforce_full_fill_volume); OPT_PTR(external_infill_margin); OPT_PTR(external_perimeter_extrusion_width); - OPT_PTR(external_perimeter_overlap); OPT_PTR(external_perimeter_speed); OPT_PTR(external_perimeters_first); OPT_PTR(external_perimeters_vase); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 7b43f1dd4..c75817451 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -305,7 +305,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("overhangs_reverse_threshold", config->opt_bool("overhangs_reverse")); toggle_field("min_width_top_surface", config->opt_bool("only_one_perimeter_top")); - for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole"}) + for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole", "perimeter_bonding"}) toggle_field(el, config->opt_bool("external_perimeters_first")); for (auto el : { "thin_walls_min_width", "thin_walls_overlap" }) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 745481b6e..afabac225 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -536,6 +536,8 @@ const std::vector& Preset::print_options() "print_extrusion_multiplier", "external_perimeter_cut_corners", "external_perimeter_overlap", + "perimeter_bonding", + "perimeter_overlap", "milling_after_z", "milling_post_process", "milling_extra_size", diff --git a/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp index 1901ce2cd..9a3e8fee5 100644 --- a/src/slic3r/GUI/PresetHints.cpp +++ b/src/slic3r/GUI/PresetHints.cpp @@ -319,6 +319,9 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre *print_config.opt("perimeter_extrusion_width"), nozzle_diameter, layer_height, false); + //set spacing + external_perimeter_flow.spacing_ratio = print_config.opt("external_perimeter_overlap")->get_abs_value(1); + perimeter_flow.spacing_ratio = print_config.opt("perimeter_overlap")->get_abs_value(1); if (num_perimeters > 0) { int num_lines = std::min(num_perimeters, 6);