From c75d4904f9b75a301f683f3d1cd2d8259e75c768 Mon Sep 17 00:00:00 2001 From: supermerill Date: Fri, 9 Oct 2020 00:28:00 +0200 Subject: [PATCH] #493 separate bridge fan/speed for overhang from bridge flow for overhangs. --- resources/ui_layout/print.ui | 6 +- src/libslic3r/Layer.cpp | 2 +- src/libslic3r/PerimeterGenerator.cpp | 129 ++++++++++-------- src/libslic3r/PerimeterGenerator.hpp | 6 +- src/libslic3r/PrintConfig.cpp | 32 +++-- src/libslic3r/PrintConfig.hpp | 4 +- src/libslic3r/PrintObject.cpp | 2 +- src/libslic3r/SupportMaterial.cpp | 2 +- .../GUI/CalibrationRetractionDialog.cpp | 2 +- src/slic3r/GUI/ConfigManipulation.cpp | 8 +- src/slic3r/GUI/Preset.cpp | 3 +- 11 files changed, 116 insertions(+), 80 deletions(-) diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 3e5f5a09a..640b859e1 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -40,9 +40,9 @@ group:Quality setting:thin_walls_merge end_line group:Overhangs - line:On perimeters - setting:sidetext_width$1:overhangs - setting:width$5:overhangs_width + line:threshold for + setting:label$bridge speed and fan:width$5:overhangs_width_speed + setting:label$bridge flow:width$5:overhangs_width end_line line:Extrusion direction setting:sidetext_width$1:overhangs_reverse diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index d8fa37bb4..46f75bba5 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -153,7 +153,7 @@ void Layer::make_perimeters() && config.infill_dense_algo == other_config.infill_dense_algo && config.no_perimeter_unsupported_algo == other_config.no_perimeter_unsupported_algo && config.only_one_perimeter_top == other_config.only_one_perimeter_top - && config.overhangs == other_config.overhangs + && config.overhangs_width_speed == other_config.overhangs_width_speed && config.overhangs_width == other_config.overhangs_width && config.overhangs_reverse == other_config.overhangs_reverse && config.overhangs_reverse_threshold == other_config.overhangs_reverse_threshold diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 1d818b639..65bf2ae98 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -97,12 +97,16 @@ void PerimeterGenerator::process() coord_t ext_min_spacing = (coord_t)( ext_perimeter_spacing2 * (1 - 0.05/*INSET_OVERLAP_TOLERANCE*/) ); // prepare grown lower layer slices for overhang detection - if (this->lower_slices != NULL && this->config->overhangs) { + if (this->lower_slices != NULL && this->config->overhangs_width > 0) { // We consider overhang any part where the entire nozzle diameter is not supported by the - // lower layer, so we take lower slices and offset them by half the nozzle diameter used + // lower layer, so we take lower slices and offset them by overhangs_width of the nozzle diameter used // in the current layer double offset_val = double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2); - this->_lower_slices_p = offset(*this->lower_slices, offset_val); + this->_lower_slices_bridge_flow = offset(*this->lower_slices, offset_val); + } + if (this->lower_slices != NULL && this->config->overhangs_width_speed > 0) { + double offset_val = double(scale_(config->overhangs_width_speed.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2); + this->_lower_slices_bridge_speed = offset(*this->lower_slices, offset_val); } // have to grown the perimeters if mill post-process @@ -942,6 +946,69 @@ void PerimeterGenerator::process() } // for each island } +template +ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const { + ExtrusionPaths paths; + double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1); + if (this->config->overhangs_width.get_abs_value(nozzle_diameter) > this->config->overhangs_width_speed.get_abs_value(nozzle_diameter)) { + // get non-overhang paths by intersecting this loop with the grown lower slices + extrusion_paths_append( + paths, + intersection_pl(loop_polygons, this->_lower_slices_bridge_speed), + role, + is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, + is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, + (float)this->layer->height); + + // get overhang paths by checking what parts of this loop fall + // outside the grown lower slices + Polylines poly_speed = diff_pl(loop_polygons, this->_lower_slices_bridge_speed); + + extrusion_paths_append( + paths, + intersection_pl(poly_speed, this->_lower_slices_bridge_flow), + erOverhangPerimeter, + is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, + is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, + (float)this->layer->height); + + extrusion_paths_append( + paths, + diff_pl(poly_speed, this->_lower_slices_bridge_flow), + erOverhangPerimeter, + this->_mm3_per_mm_overhang, + this->overhang_flow.width, + this->overhang_flow.height); + + } else { + + // get non-overhang paths by intersecting this loop with the grown lower slices + extrusion_paths_append( + paths, + intersection_pl(loop_polygons, this->_lower_slices_bridge_flow), + role, + is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, + is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, + (float)this->layer->height); + + // get overhang paths by checking what parts of this loop fall + // outside the grown lower slices + extrusion_paths_append( + paths, + diff_pl(loop_polygons, this->_lower_slices_bridge_flow), + erOverhangPerimeter, + this->_mm3_per_mm_overhang, + this->overhang_flow.width, + this->overhang_flow.height); + } + + // reapply the nearest point search for starting point + // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. + if(!paths.empty()) + chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); + return paths; +} + ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const { @@ -971,31 +1038,9 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( // detect overhanging/bridging perimeters ExtrusionPaths paths; - if (this->config->overhangs && this->layer->id() > 0 + if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0 && !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) { - // get non-overhang paths by intersecting this loop with the grown lower slices - extrusion_paths_append( - paths, - intersection_pl(loop.polygon, this->_lower_slices_p), - role, - is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, - is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, - (float) this->layer->height); - - // get overhang paths by checking what parts of this loop fall - // outside the grown lower slices (thus where the distance between - // the loop centerline and original lower slices is >= half nozzle diameter - extrusion_paths_append( - paths, - diff_pl(loop.polygon, this->_lower_slices_p), - erOverhangPerimeter, - this->_mm3_per_mm_overhang, - this->overhang_flow.width, - this->overhang_flow.height); - - // reapply the nearest point search for starting point - // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. - chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); + paths = this->create_overhangs(loop.polygon, role, is_external); } else { ExtrusionPath path(role); path.polyline = loop.polygon.split_at_first_point(); @@ -1423,35 +1468,9 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co } // detect overhanging/bridging perimeters - if (this->config->overhangs && this->layer->id() > 0 + if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0 && !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) { - ExtrusionPaths paths; - // get non-overhang paths by intersecting this loop with the grown lower slices - extrusion_paths_append( - paths, - intersection_pl(initial_polyline, this->_lower_slices_p), - role, - is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, - is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, - (float) this->layer->height); - - // get overhang paths by checking what parts of this loop fall - // outside the grown lower slices (thus where the distance between - // the loop centerline and original lower slices is >= half nozzle diameter - extrusion_paths_append( - paths, - diff_pl(initial_polyline, this->_lower_slices_p), - erOverhangPerimeter, - this->_mm3_per_mm_overhang, - this->overhang_flow.width, - this->overhang_flow.height); - - // reapply the nearest point search for starting point - // We allow polyline reversal because Clipper may have randomly - // reversed polylines during clipping. - if (!paths.empty()) - chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); - + ExtrusionPaths paths = this->create_overhangs(initial_polyline, role, is_external); if (direction.length() > 0) { Polyline direction_polyline; diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index 363e4d492..0ae116fb7 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -96,7 +96,11 @@ private: double _ext_mm3_per_mm; double _mm3_per_mm; double _mm3_per_mm_overhang; - Polygons _lower_slices_p; + Polygons _lower_slices_bridge_flow; + Polygons _lower_slices_bridge_speed; + + template + ExtrusionPaths create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const; // transform loops into ExtrusionEntityCollection, adding also thin walls into it. ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 64661b8ef..0b148b1da 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2345,23 +2345,29 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionString("[input_filename_base].gcode")); - def = this->add("overhangs", coBool); - def->label = L("As bridge"); - def->full_label = L("Overhangs as bridge"); + def = this->add("overhangs_width_speed", coFloatOrPercent); + def->label = L("'As bridge' speed threshold"); + def->full_label = L("Overhang bridge speed threshold"); def->category = OptionCategory::perimeter; - def->tooltip = L("Option to adjust flow for overhangs (bridge flow will be used), " - "to apply bridge speed to them and enable fan."); + def->tooltip = L("Minimum unsupported width for an extrusion to apply the bridge speed & fan to this overhang." + " Can be in mm or in a % of the nozzle diameter." + " Set to 0 to deactivate."); + def->ratio_over = "nozzle_diameter"; + def->min = 0; def->mode = comExpert; - def->set_default_value(new ConfigOptionBool(true)); + def->set_default_value(new ConfigOptionFloatOrPercent(50,true)); def = this->add("overhangs_width", coFloatOrPercent); - def->label = L("'As bridge' threshold"); - def->full_label = L("Overhang bridge threshold"); + def->label = L("'As bridge' flow threshold"); + def->full_label = L("Overhang bridge flow threshold"); def->category = OptionCategory::perimeter; - def->tooltip = L("Minimum unsupported width for an extrusion to be considered an overhang. Can be in mm or in a % of the nozzle diameter."); + def->tooltip = L("Minimum unsupported width for an extrusion to apply the bridge flow to this overhang." + " Can be in mm or in a % of the nozzle diameter." + " Set to 0 to deactivate."); def->ratio_over = "nozzle_diameter"; + def->min = 0; def->mode = comExpert; - def->set_default_value(new ConfigOptionFloatOrPercent(50, true)); + def->set_default_value(new ConfigOptionFloatOrPercent(75, true)); def = this->add("overhangs_reverse", coBool); def->label = L("Reverse on odd"); @@ -4629,6 +4635,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va value = "notconnected"; else value = "connected"; + } else if (opt_key == "overhangs") { + opt_key = "overhangs_width_speed"; + if (value == "1") + value = "50%"; + else + value = "0"; } // Ignore the following obsolete configuration keys: diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 8201963d6..5c0fff9de 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -694,8 +694,8 @@ public: ConfigOptionFloat milling_speed; ConfigOptionFloatOrPercent min_width_top_surface; // Detect bridging perimeters - ConfigOptionBool overhangs; ConfigOptionFloatOrPercent overhangs_width; + ConfigOptionFloatOrPercent overhangs_width_speed; ConfigOptionBool overhangs_reverse; ConfigOptionFloatOrPercent overhangs_reverse_threshold; ConfigOptionEnum no_perimeter_unsupported_algo; @@ -786,8 +786,8 @@ protected: OPT_PTR(milling_post_process); OPT_PTR(milling_speed); OPT_PTR(min_width_top_surface); - OPT_PTR(overhangs); OPT_PTR(overhangs_width); + OPT_PTR(overhangs_width_speed); OPT_PTR(overhangs_reverse); OPT_PTR(overhangs_reverse_threshold); OPT_PTR(no_perimeter_unsupported_algo); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d97155cd4..4c387fc20 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -614,7 +614,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorfill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); - if (region->region()->config().overhangs.value) + if (region->region()->config().overhangs_width.value > 0) SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming); } if (! some_region_overlaps) diff --git a/src/slic3r/GUI/CalibrationRetractionDialog.cpp b/src/slic3r/GUI/CalibrationRetractionDialog.cpp index 6eae18472..035e7fb4f 100644 --- a/src/slic3r/GUI/CalibrationRetractionDialog.cpp +++ b/src/slic3r/GUI/CalibrationRetractionDialog.cpp @@ -210,7 +210,7 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) { model.objects[objs_idx[i]]->config.set_key_value("fill_density", new ConfigOptionPercent(0)); //model.objects[objs_idx[i]]->config.set_key_value("fill_pattern", new ConfigOptionEnum(ipRectilinear)); model.objects[objs_idx[i]]->config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false)); - model.objects[objs_idx[i]]->config.set_key_value("overhangs", new ConfigOptionBool(false)); + model.objects[objs_idx[i]]->config.set_key_value("overhangs_width_speed", new ConfigOptionFloatOrPercent(0,false)); model.objects[objs_idx[i]]->config.set_key_value("thin_walls", new ConfigOptionBool(true)); model.objects[objs_idx[i]]->config.set_key_value("thin_walls_min_width", new ConfigOptionFloatOrPercent(2,true)); model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(false)); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index de205f5cb..7c4bd51db 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -276,9 +276,9 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con // Ask only once. if (!support_material_overhangs_queried) { support_material_overhangs_queried = true; - if (!config->opt_bool("overhangs")/* != 1*/) { + if (config->option("overhangs_width_speed") == 0) { wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n" - "- Detect bridging perimeters")); + "- overhangs with bridge speed & fan")); if (is_global_config) { msg_text += "\n\n" + _(L("Shall I adjust those settings for supports?")); wxMessageDialog dialog(nullptr, msg_text, _(L("Support Generator")), @@ -287,7 +287,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con auto answer = dialog.ShowModal(); if (!is_global_config || answer == wxID_YES) { // Enable "detect bridging perimeters". - new_conf.set_key_value("overhangs", new ConfigOptionBool(true)); + new_conf.set_key_value("overhangs_width_speed", new ConfigOptionFloatOrPercent(50, true)); } else if (answer == wxID_NO) { // Do nothing, leave supports on and "detect bridging perimeters" off. } else if (answer == wxID_CANCEL) { @@ -362,7 +362,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop", "perimeter_loop_seam" }) toggle_field(el, have_perimeters); - toggle_field("overhangs_width", config->opt_bool("overhangs")); + toggle_field("overhangs_width", config->option("overhangs_width_speed")->value > 0); toggle_field("overhangs_reverse_threshold", config->opt_bool("overhangs_reverse")); toggle_field("min_width_top_surface", config->opt_bool("only_one_perimeter_top")); toggle_field("thin_perimeters_all", config->opt_bool("thin_perimeters")); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index c98a679eb..d9070106f 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -439,8 +439,9 @@ const std::vector& Preset::print_options() "avoid_crossing_perimeters", "avoid_crossing_not_first_layer", "thin_perimeters", "thin_perimeters_all", - "thin_walls", "overhangs", + "thin_walls", "overhangs_width", + "overhangs_width_speed", "overhangs_reverse", "overhangs_reverse_threshold", "seam_position",