From 00db3dc41937670e91c26170c9c168bf75a86aaf Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 9 Mar 2021 15:29:13 +0100 Subject: [PATCH] WIP: Splitting the number of top / bottom support interface layers. If the new support_material_bottom_interface_layers is left at default -1, then support_material_interface_layers is used for both top and bottom interface layers. If support_material_interface_layers == 0, then neither top nor bottom interface layers are being extruded. --- src/libslic3r/Flow.hpp | 5 +- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 12 ++- src/libslic3r/PrintConfig.hpp | 2 + src/libslic3r/PrintObject.cpp | 1 + src/libslic3r/SupportMaterial.cpp | 105 +++++++++++++++----------- src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 8 files changed, 81 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp index 428d31c1f..04ced3e13 100644 --- a/src/libslic3r/Flow.hpp +++ b/src/libslic3r/Flow.hpp @@ -118,7 +118,10 @@ public: private: Flow(float width, float height, float spacing, float nozzle_diameter, bool bridge) : m_width(width), m_height(height), m_spacing(spacing), m_nozzle_diameter(nozzle_diameter), m_bridge(bridge) - { assert(width >= height); } + { + // Gap fill violates this condition. + //assert(width >= height); + } float m_width { 0 }; float m_height { 0 }; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 81a14eaec..412dbc678 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -428,7 +428,7 @@ const std::vector& Preset::print_options() "min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", - "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", + "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers", "support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance", "support_material_buildplate_only", "dont_support_bridges", "thick_bridges", "notes", "complete_objects", "extruder_clearance_radius", "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b87042b89..d744cb2a7 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2299,7 +2299,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionInt(1)); def = this->add("support_material_interface_layers", coInt); - def->label = L("Interface layers"); + def->label = L("Top interface layers"); def->category = L("Support material"); def->tooltip = L("Number of interface layers to insert between the object(s) and support material."); def->sidetext = L("layers"); @@ -2307,6 +2307,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionInt(3)); + def = this->add("support_material_bottom_interface_layers", coInt); + def->label = L("Bottom interface layers"); + def->category = L("Support material"); + def->tooltip = L("Number of interface layers to insert between the object(s) and support material. " + "Set to -1 to use support_material_interface_layers"); + def->sidetext = L("layers"); + def->min = -1; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionInt(-1)); + def = this->add("support_material_interface_spacing", coFloat); def->label = L("Interface pattern spacing"); def->category = L("Support material"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c92abf51f..4a4647b73 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -509,6 +509,7 @@ public: ConfigOptionBool support_material_interface_contact_loops; ConfigOptionInt support_material_interface_extruder; ConfigOptionInt support_material_interface_layers; + ConfigOptionInt support_material_bottom_interface_layers; // Spacing between interface lines (the hatching distance). Set zero to get a solid interface. ConfigOptionFloat support_material_interface_spacing; ConfigOptionFloatOrPercent support_material_interface_speed; @@ -560,6 +561,7 @@ protected: OPT_PTR(support_material_extrusion_width); OPT_PTR(support_material_interface_extruder); OPT_PTR(support_material_interface_layers); + OPT_PTR(support_material_bottom_interface_layers); OPT_PTR(support_material_interface_spacing); OPT_PTR(support_material_interface_speed); OPT_PTR(support_material_pattern); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 3fe5f2421..a3b0fb787 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -587,6 +587,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_extruder" || opt_key == "support_material_extrusion_width" || opt_key == "support_material_interface_layers" + || opt_key == "support_material_bottom_interface_layers" || opt_key == "support_material_interface_pattern" || opt_key == "support_material_interface_contact_loops" || opt_key == "support_material_interface_extruder" diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index b68d1f2c3..7747559e6 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2720,17 +2720,23 @@ std::pairsupport_material_interface_extruder.value > 0 && m_print_config->filament_soluble.get_at(m_object_config->support_material_interface_extruder.value - 1) && // Base extruder: Either "print with active extruder" not soluble. (m_object_config->support_material_extruder.value == 0 || ! m_print_config->filament_soluble.get_at(m_object_config->support_material_extruder.value - 1)); - int num_interface_layers = m_object_config->support_material_interface_layers.value; - int num_base_interface_layers = soluble_interface_non_soluble_base ? std::min(num_interface_layers / 2, 2) : 0; + int num_interface_layers_top = m_object_config->support_material_interface_layers; + int num_interface_layers_bottom = m_object_config->support_material_bottom_interface_layers; + if (num_interface_layers_bottom < 0) + num_interface_layers_bottom = num_interface_layers_top; + int num_base_interface_layers_top = soluble_interface_non_soluble_base ? std::min(num_interface_layers_top / 2, 2) : 0; + int num_base_interface_layers_bottom = soluble_interface_non_soluble_base ? std::min(num_interface_layers_bottom / 2, 2) : 0; - if (! intermediate_layers.empty() && num_interface_layers > 1) { + if (! intermediate_layers.empty() && (num_interface_layers_top > 1 || num_interface_layers_bottom > 1)) { // For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers. BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start"; // Since the intermediate layer index starts at zero the number of interface layer needs to be reduced by 1. - -- num_interface_layers; - int num_interface_layers_only = num_interface_layers - num_base_interface_layers; + -- num_interface_layers_top; + -- num_interface_layers_bottom; + int num_interface_layers_only_top = num_interface_layers_top - num_base_interface_layers_top; + int num_interface_layers_only_bottom = num_interface_layers_bottom - num_base_interface_layers_bottom; interface_layers.assign(intermediate_layers.size(), nullptr); - if (num_base_interface_layers) + if (num_base_interface_layers_top || num_base_interface_layers_bottom) base_interface_layers.assign(intermediate_layers.size(), nullptr); tbb::spin_mutex layer_storage_mutex; // Insert a new layer into base_interface_layers, if intersection with base exists. @@ -2754,7 +2760,8 @@ std::pair(0, int(intermediate_layers.size())), - [&bottom_contacts, &top_contacts, &intermediate_layers, &insert_layer, num_interface_layers, num_base_interface_layers, num_interface_layers_only, + [&bottom_contacts, &top_contacts, &intermediate_layers, &insert_layer, + num_interface_layers_top, num_interface_layers_bottom, num_base_interface_layers_top, num_base_interface_layers_bottom, num_interface_layers_only_top, num_interface_layers_only_bottom, &interface_layers, &base_interface_layers](const tbb::blocked_range& range) { // Gather the top / bottom contact layers intersecting with num_interface_layers resp. num_interface_layers_only intermediate layers above / below // this intermediate layer. @@ -2765,45 +2772,51 @@ std::pairprint_z; - coordf_t top_inteface_z = std::numeric_limits::max(); - coordf_t bottom_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers + 1)]->bottom_z; - coordf_t bottom_interface_z = - std::numeric_limits::max(); - if (num_base_interface_layers > 0) { - // Some base interface layers will be generated. - if (num_interface_layers_only == 0) - // Only base interface layers to generate. - std::swap(top_inteface_z, bottom_interface_z); - else { - top_inteface_z = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only - 1)]->print_z; - bottom_interface_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only)]->bottom_z; - } - } - // Move idx_top_contact_first up until above the current print_z. - idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON - // Collect the top contact areas above this intermediate layer, below top_z. Polygons polygons_top_contact_projected_interface; Polygons polygons_top_contact_projected_base; - for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) { - const MyLayer &top_contact_layer = *top_contacts[idx_top_contact]; - //FIXME maybe this adds one interface layer in excess? - if (top_contact_layer.bottom_z - EPSILON > top_z) - break; - polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface, top_contact_layer.polygons); - } - // Move idx_bottom_contact_first up until touching bottom_z. - idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; }); - // Collect the top contact areas above this intermediate layer, below top_z. Polygons polygons_bottom_contact_projected_interface; Polygons polygons_bottom_contact_projected_base; - for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) { - const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact]; - if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z) - break; - polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons); + if (num_interface_layers_top > -1) { + // Top Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces + coordf_t top_z = intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_top - 1)]->print_z; + coordf_t top_inteface_z = std::numeric_limits::max(); + if (num_base_interface_layers_top > 0) + // Some top base interface layers will be generated. + top_inteface_z = num_interface_layers_only_top == 0 ? + // Only base interface layers to generate. + - std::numeric_limits::max() : + intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only_top - 1)]->print_z; + // Move idx_top_contact_first up until above the current print_z. + idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON + // Collect the top contact areas above this intermediate layer, below top_z. + for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) { + const MyLayer &top_contact_layer = *top_contacts[idx_top_contact]; + //FIXME maybe this adds one interface layer in excess? + if (top_contact_layer.bottom_z - EPSILON > top_z) + break; + polygons_append(top_contact_layer.bottom_z - EPSILON > top_inteface_z ? polygons_top_contact_projected_base : polygons_top_contact_projected_interface, top_contact_layer.polygons); + } + } + if (num_interface_layers_bottom > -1) { + // Bottom Z coordinate of a slab, over which we are collecting the top / bottom contact surfaces + coordf_t bottom_z = intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_bottom + 1)]->bottom_z; + coordf_t bottom_interface_z = - std::numeric_limits::max(); + if (num_base_interface_layers_bottom > 0) + // Some bottom base interface layers will be generated. + bottom_interface_z = num_interface_layers_only_bottom == 0 ? + // Only base interface layers to generate. + std::numeric_limits::max() : + intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only_bottom)]->bottom_z; + // Move idx_bottom_contact_first up until touching bottom_z. + idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; }); + // Collect the top contact areas above this intermediate layer, below top_z. + for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) { + const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact]; + if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z) + break; + polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons); + } } - MyLayer *interface_layer = nullptr; if (! polygons_bottom_contact_projected_interface.empty() || ! polygons_top_contact_projected_interface.empty()) { interface_layer = insert_layer( @@ -3712,10 +3725,6 @@ void PrintObjectSupportMaterial::generate_toolpaths( base_layer.merge(std::move(top_contact_layer)); else if (base_layer.empty() && !top_contact_layer.empty() && !top_contact_layer.layer->bridging) std::swap(base_layer, top_contact_layer); - if (base_layer.could_merge(bottom_contact_layer)) - base_layer.merge(std::move(bottom_contact_layer)); - else if (base_layer.empty() && !bottom_contact_layer.empty() && !bottom_contact_layer.layer->bridging) - std::swap(base_layer, bottom_contact_layer); } } else { loop_interface_processor.generate(top_contact_layer, m_support_material_interface_flow); @@ -3725,6 +3734,12 @@ void PrintObjectSupportMaterial::generate_toolpaths( if (top_contact_layer.could_merge(interface_layer)) top_contact_layer.merge(std::move(interface_layer)); } + if ((m_object_config->support_material_interface_layers == 0 || m_object_config->support_material_bottom_interface_layers == 0) && m_can_merge_support_regions) { + if (base_layer.could_merge(bottom_contact_layer)) + base_layer.merge(std::move(bottom_contact_layer)); + else if (base_layer.empty() && !bottom_contact_layer.empty() && !bottom_contact_layer.layer->bridging) + std::swap(base_layer, bottom_contact_layer); + } #if 0 if ( ! interface_layer.empty() && ! base_layer.empty()) { diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 01ec72837..80ebe6ea8 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -286,7 +286,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field(el, have_support_material); toggle_field("support_material_threshold", have_support_material_auto); - for (auto el : { "support_material_interface_spacing", "support_material_interface_extruder", + for (auto el : { "support_material_bottom_interface_layers", "support_material_interface_spacing", "support_material_interface_extruder", "support_material_interface_speed", "support_material_interface_contact_loops" }) toggle_field(el, have_support_material && have_support_interface); toggle_field("support_material_synchronize_layers", have_support_soluble); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 645d31f4b..472db4976 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1512,6 +1512,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf"); optgroup->append_single_option_line("support_material_angle", category_path + "pattern-angle"); optgroup->append_single_option_line("support_material_interface_layers", category_path + "interface-layers"); + optgroup->append_single_option_line("support_material_bottom_interface_layers", category_path + "interface-layers"); optgroup->append_single_option_line("support_material_interface_pattern", category_path + "interface-pattern"); optgroup->append_single_option_line("support_material_interface_spacing", category_path + "interface-pattern-spacing"); optgroup->append_single_option_line("support_material_interface_contact_loops", category_path + "interface-loops");