From 4ed4ec0151849351e773302e9451af34e96dc935 Mon Sep 17 00:00:00 2001 From: remi durand Date: Tue, 8 Jun 2021 19:03:59 +0200 Subject: [PATCH] Fix sequential printing distance detection * fix bug with skirt width * always takes brim into account --- src/libslic3r/Arrange.hpp | 2 +- src/libslic3r/Flow.cpp | 128 +++++++++++++++++++++++++--------- src/libslic3r/Flow.hpp | 2 + src/libslic3r/Print.cpp | 41 +++-------- src/libslic3r/PrintConfig.cpp | 52 ++++++++------ src/slic3r/GUI/Plater.cpp | 8 ++- 6 files changed, 144 insertions(+), 89 deletions(-) diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index 496489d3e..28e327dc4 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -46,7 +46,7 @@ struct ArrangePolygon { ExPolygon poly; /// The 2D silhouette to be arranged Vec2crd translation{0, 0}; /// The translation of the poly double rotation{0.0}; /// The rotation of the poly in radians - coord_t inflation = 0; /// Arrange with inflated polygon + //coord_t inflation = 0; /// Arrange with inflated polygon int bed_idx{UNARRANGED}; /// To which logical bed does poly belong... int priority{0}; diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index a44f1c07f..72e3ecb94 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -64,50 +64,112 @@ static inline void throw_on_missing_variable(const std::string &opt_key, const c // Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser. double Flow::extrusion_width(const std::string& opt_key, const ConfigOptionFloatOrPercent* opt, const ConfigOptionResolver& config, const unsigned int first_printing_extruder) { - assert(opt != nullptr); + assert(opt != nullptr); - bool first_layer = boost::starts_with(opt_key, "first_layer_"); + bool first_layer = boost::starts_with(opt_key, "first_layer_") || boost::starts_with(opt_key, "brim_"); + if (!first_layer && boost::starts_with(opt_key, "skirt_")) { + const ConfigOptionInt* optInt = config.option("skirt_height"); + const ConfigOptionBool* optBool = config.option("draft_shield"); + first_layer = (optBool && optInt && optInt->value == 1 && !optBool->value); + } -#if 0 -// This is the logic used for skit / brim, but not for the rest of the 1st layer. - if (opt->value == 0. && first_layer) { - // The "first_layer_extrusion_width" was set to zero, try a substitute. - opt = config.option("perimeter_extrusion_width"); - if (opt == nullptr) - throw_on_missing_variable(opt_key, "perimeter_extrusion_width"); + if (opt->value == 0.) { + // The role specific extrusion width value was set to zero, get a not-0 one (if possible) + opt = extrusion_option(opt_key, config); + } + + if (opt->percent) { + auto opt_key_layer_height = first_layer ? "first_layer_height" : "layer_height"; + auto opt_layer_height = config.option(opt_key_layer_height); + if (opt_layer_height == nullptr) + throw_on_missing_variable(opt_key, opt_key_layer_height); + // first_layer_height depends on first_printing_extruder + auto opt_nozzle_diameters = config.option("nozzle_diameter"); + if (opt_nozzle_diameters == nullptr) + throw_on_missing_variable(opt_key, "nozzle_diameter"); + return opt->get_abs_value(float(opt_nozzle_diameters->get_at(first_printing_extruder))); + } + + if (opt->value == 0.) { + // If user left option to 0, calculate a sane default width. + auto opt_nozzle_diameters = config.option("nozzle_diameter"); + if (opt_nozzle_diameters == nullptr) + throw_on_missing_variable(opt_key, "nozzle_diameter"); + return auto_extrusion_width(opt_key_to_flow_role(opt_key), float(opt_nozzle_diameters->get_at(first_printing_extruder))); + } + + return opt->value; +} + +//used to get brim & skirt extrusion config +const ConfigOptionFloatOrPercent* Flow::extrusion_option(const std::string& opt_key, const ConfigOptionResolver& config) +{ + + const ConfigOptionFloatOrPercent* opt = config.option(opt_key); + + //brim is first_layer_extrusion_width then perimeter_extrusion_width + if (!opt && boost::starts_with(opt_key, "brim_")) { + const ConfigOptionFloatOrPercent* optTest = config.option("first_layer_extrusion_width"); + opt = optTest; + if (opt == nullptr) + throw_on_missing_variable(opt_key, "first_layer_extrusion_width"); + if (opt->value == 0) { + opt = config.option("perimeter_extrusion_width"); + if (opt == nullptr) + throw_on_missing_variable(opt_key, "perimeter_extrusion_width"); + } + } + + if (opt == nullptr) + throw_on_missing_variable(opt_key, opt_key.c_str()); + + // This is the logic used for skit / brim, but not for the rest of the 1st layer. + if (opt->value == 0. && boost::starts_with(opt_key, "skirt")) { + // The "skirt_extrusion_width" was set to zero, try a substitute. + const ConfigOptionFloatOrPercent* optTest = config.option("first_layer_extrusion_width"); + const ConfigOptionInt* optInt = config.option("skirt_height"); + const ConfigOptionBool* optBool = config.option("draft_shield"); + if (optTest == nullptr) + throw_on_missing_variable(opt_key, "first_layer_extrusion_width"); + if (optBool == nullptr) + throw_on_missing_variable(opt_key, "draft_shield"); + if (optInt == nullptr) + throw_on_missing_variable(opt_key, "skirt_height"); + // The "first_layer_extrusion_width" was set to zero, try a substitute. + if (optTest && optBool && optInt && optTest->value > 0 && optInt->value == 1 && !optBool->value) + opt = optTest; + + if (opt->value == 0) { + opt = config.option("perimeter_extrusion_width"); + if (opt == nullptr) + throw_on_missing_variable(opt_key, "perimeter_extrusion_width"); + } } -#endif + + // external_perimeter_extrusion_width default is perimeter_extrusion_width + if (opt->value == 0. && boost::starts_with(opt_key, "external_perimeter_extrusion_width")) { + // The role specific extrusion width value was set to zero, try the role non-specific extrusion width. + opt = config.option("perimeter_extrusion_width"); + if (opt == nullptr) + throw_on_missing_variable(opt_key, "perimeter_extrusion_width"); + } + + // top_infill_extrusion_width default is solid_infill_extrusion_width + if (opt->value == 0. && boost::starts_with(opt_key, "top_infill_extrusion_width")) { + // The role specific extrusion width value was set to zero, try the role non-specific extrusion width. + opt = config.option("solid_infill_extrusion_width"); + if (opt == nullptr) + throw_on_missing_variable(opt_key, "perimeter_extrusion_width"); + } if (opt->value == 0.) { // The role specific extrusion width value was set to zero, try the role non-specific extrusion width. opt = config.option("extrusion_width"); if (opt == nullptr) throw_on_missing_variable(opt_key, "extrusion_width"); - // Use the "layer_height" instead of "first_layer_height". - first_layer = false; } - if (opt->percent) { - auto opt_key_layer_height = first_layer ? "first_layer_height" : "layer_height"; - auto opt_layer_height = config.option(opt_key_layer_height); - if (opt_layer_height == nullptr) - throw_on_missing_variable(opt_key, opt_key_layer_height); - // first_layer_height depends on first_printing_extruder - auto opt_nozzle_diameters = config.option("nozzle_diameter"); - if (opt_nozzle_diameters == nullptr) - throw_on_missing_variable(opt_key, "nozzle_diameter"); - return opt->get_abs_value(float(opt_nozzle_diameters->get_at(first_printing_extruder))); - } - - if (opt->value == 0.) { - // If user left option to 0, calculate a sane default width. - auto opt_nozzle_diameters = config.option("nozzle_diameter"); - if (opt_nozzle_diameters == nullptr) - throw_on_missing_variable(opt_key, "nozzle_diameter"); - return auto_extrusion_width(opt_key_to_flow_role(opt_key), float(opt_nozzle_diameters->get_at(first_printing_extruder))); - } - - return opt->value; + return opt; } // Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser. diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp index 78d572a55..99fe93bad 100644 --- a/src/libslic3r/Flow.hpp +++ b/src/libslic3r/Flow.hpp @@ -106,6 +106,8 @@ public: // on active extruder etc. Therefore the value calculated by this function shall be used as a hint only. static double extrusion_width(const std::string &opt_key, const ConfigOptionFloatOrPercent *opt, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0); static double extrusion_width(const std::string &opt_key, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0); + static const ConfigOptionFloatOrPercent* extrusion_option(const std::string& opt_key, const ConfigOptionResolver& config); + }; extern Flow support_material_flow(const PrintObject *object, float layer_height = 0.f); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a9959a695..ba868f95e 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1658,20 +1658,12 @@ double Print::skirt_first_layer_height() const Flow Print::brim_flow(size_t extruder_id, const PrintObjectConfig& brim_config) const { - ConfigOptionFloatOrPercent width = brim_config.first_layer_extrusion_width; - if (width.value <= 0) - width = m_default_region_config.perimeter_extrusion_width; - if (width.value <= 0) - width = brim_config.extrusion_width; - - /* We currently use a random region's perimeter extruder. - While this works for most cases, we should probably consider all of the perimeter - extruders and take the one with, say, the smallest index. - The same logic should be applied to the code that selects the extruder during G-code - generation as well. */ + //use default region, but current object config. + PrintRegionConfig tempConf = m_default_region_config; + tempConf.parent = &brim_config; return Flow::new_from_config_width( frPerimeter, - width, + *Flow::extrusion_option("brim_extrusion_width", tempConf), (float)m_config.nozzle_diameter.get_at(extruder_id), (float)this->skirt_first_layer_height() ); @@ -1679,27 +1671,14 @@ Flow Print::brim_flow(size_t extruder_id, const PrintObjectConfig& brim_config) Flow Print::skirt_flow(size_t extruder_id) const { - ConfigOptionFloatOrPercent width = m_config.skirt_extrusion_width; - if (width.value <= 0 && m_default_object_config.first_layer_extrusion_width.value > 0 - && m_config.skirt_height == 1 && !m_config.draft_shield) - width = m_default_object_config.first_layer_extrusion_width; - if (width.value <= 0) - width = m_default_region_config.perimeter_extrusion_width; - if (width.value <= 0) - width = m_default_object_config.extrusion_width; - - /* We currently use a random object's support material extruder. - While this works for most cases, we should probably consider all of the support material - extruders and take the one with, say, the smallest index; - The same logic should be applied to the code that selects the extruder during G-code - generation as well. */ - /* or select the used extruder with the highest nozzle diameter, to be on the safe side.*/ + //send m_default_object_config becasue it's the lowest config needed (extrusion_option need config from object & print) return Flow::new_from_config_width( frPerimeter, - width, - (float)m_config.nozzle_diameter.get_at(extruder_id), - (float)this->skirt_first_layer_height() + *Flow::extrusion_option("skirt_extrusion_width", m_default_region_config), + (float)m_config.nozzle_diameter.get_at(extruder_id), + (float)this->skirt_first_layer_height() ); + } bool Print::has_support_material() const @@ -1855,7 +1834,7 @@ void Print::process() std::vector set_extruders = this->object_extruders(m_objects); append(set_extruders, this->support_material_extruders()); sort_remove_duplicates(set_extruders); - Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front(), obj_group.front()->config()); + Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front(), m_default_object_config); if (brim_config.brim_ears) this->_make_brim_ears(flow, obj_group, brim_area, m_brim); else diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a9559f49d..33d3cb808 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5671,48 +5671,56 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei // min object distance is max(duplicate_distance, clearance_radius) // /2 becasue we only count the grawing for the current object - //add 1 as safety offset. + //add 1 as safety offset. double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat() / 2 + 1; if (extruder_clearance_radius > base_dist) { base_dist = extruder_clearance_radius; } - //std::cout << " min_object_distance add extruder_clearance_radius ("<< extruder_clearance_radius <<") =>" << base_dist << "\n"; - //FIXME: now brim can be per-object, so you ahve to get a different min_object_distance per object //add brim width + // note: now brim can be per-object, so you have to get a different min_object_distance per object + // You should increase/reduce the size of the polygons that have a model-wide setting. const double first_layer_height = config->get_abs_value("first_layer_height"); if (ref_height <= first_layer_height && ref_height != 0) { - //FIXME: does not take into account object-defined brim !!! you can crash yoursefl with it if (config->option("brim_width")->getFloat() > 0) { brim_dist += config->option("brim_width")->getFloat(); - //std::cout << " Set brim=" << config->option("brim_width")->getFloat() << " => " << brim_dist << "\n"; } - } else if (config->option("brim_width")->getFloat() + 1 > base_dist) { - base_dist = config->option("brim_width")->getFloat(); } + else //if (config->option("brim_width")->getFloat() + 1 > base_dist) { + base_dist += config->option("brim_width")->getFloat(); + //} //add the skirt - if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() == 1 && ref_height == 0) { - skirt_dist = config->option("skirt_distance")->getFloat(); - const double first_layer_width = config->get_abs_value("skirt_extrusion_width"); - Flow flow(first_layer_width, first_layer_height, max_nozzle_diam); - skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1)); - base_dist = std::max(base_dist, skirt_dist + 1); - skirt_dist = 0; - }else if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) { - double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height; - if (ref_height <= skirt_height) { + if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) { + if (ref_height == 0) { skirt_dist = config->option("skirt_distance")->getFloat(); - const double first_layer_width = config->get_abs_value("skirt_extrusion_width"); - Flow flow(first_layer_width, first_layer_height, max_nozzle_diam); - skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1)); - //std::cout << " Set skirt_dist=" << config->option("skirt_distance")->getFloat() << " => " << skirt_dist << "\n"; + Flow skirt_flow = Flow::new_from_config_width( + frPerimeter, + *Flow::extrusion_option("skirt_extrusion_width", *config), + (float)max_nozzle_diam, + (float)first_layer_height + ); + skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1)); + base_dist = std::max(base_dist, skirt_dist + 1); + //set to 0 becasue it's incorporated into the base_dist, so we don't want to be added in to it again. + skirt_dist = 0; + } else { + double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height; + if (ref_height <= skirt_height) { + skirt_dist = config->option("skirt_distance")->getFloat(); + Flow skirt_flow = Flow::new_from_config_width( + frPerimeter, + *Flow::extrusion_option("skirt_extrusion_width", *config), + (float)max_nozzle_diam, + (float)first_layer_height + ); + skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1)); + } } } } catch (const std::exception & ex) { boost::nowide::cerr << ex.what() << std::endl; } - //std::cout << "END min_object_distance =>" << (base_dist + std::max(skirt_dist, brim_dist)) << "\n"; return base_dist + std::max(skirt_dist, brim_dist); } return base_dist; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5988f3cab..991c0f7e2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1980,10 +1980,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) "complete_objects_one_skirt", "duplicate_distance", "extruder_clearance_radius", "skirt_extrusion_width", - "skirts", "skirt_distance", "skirt_height", + "first_layer_extrusion_width", + "perimeter_extrusion_width", + "extrusion_width", + "skirts", "skirt_distance", "skirt_height", "draft_shield", "brim_width", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", - "wipe_tower_brim", "extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology", + "wipe_tower_brim", + "extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology", // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. "layer_height", "first_layer_height", "min_layer_height", "max_layer_height", "brim_width", "perimeters", "perimeter_extruder", "fill_density", "infill_extruder", "top_solid_layers",