From 6a98c06db2e069813be2fa344bfc6274d3f3f7a1 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 1 Oct 2018 17:52:21 +0200 Subject: [PATCH] update on dense infill: add switch for the algo (good old vs bad new) --- xs/src/libslic3r/PrintConfig.cpp | 20 +++++- xs/src/libslic3r/PrintConfig.hpp | 17 ++++- xs/src/libslic3r/PrintObject.cpp | 103 ++++++++++++++++++++--------- xs/src/slic3r/GUI/Field.cpp | 8 ++- xs/src/slic3r/GUI/GUI.cpp | 4 +- xs/src/slic3r/GUI/OptionsGroup.cpp | 3 + xs/src/slic3r/GUI/Preset.cpp | 3 +- xs/src/slic3r/GUI/Tab.cpp | 13 +++- 8 files changed, 128 insertions(+), 43 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index b23ad421e..b76bb7805 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -911,12 +911,26 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionInt(1); def = this->add("infill_dense", coBool); - def->label = L("Suporting dense layer"); + def->label = (""); def->category = L("Infill"); - def->tooltip = L("Enable the creation of a support layer under the first solid layer. Allow to use lower infill ratio without compromizing the top quality"); + def->tooltip = L("Enable the creation of a support layer under the first solid layer. Allow to use lower infill ratio without compromizing the top quality." + " The dense infill is layed out with a 50% infill density."); def->cli = "infill-dense!"; def->default_value = new ConfigOptionBool(1); - + + def = this->add("infill_dense_algo", coEnum); + def->label = L("Algorithm"); + def->tooltip = L("Choose the way the dense layer is lay out." + " The automatic option let it try to draw the smallest surface with only strait lines inside the sparse infill." + " The anchored just enlarge a bit (by bridged anchor) the surfaces that need a better support."); + def->cli = "infill-dense-algo=s"; + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("automatic"); + def->enum_values.push_back("enxtended"); + def->enum_labels.push_back(L("Automatic")); + def->enum_labels.push_back(L("Anchored")); + def->default_value = new ConfigOptionEnum(dfaAutomatic); + 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 01e5a6fe7..121af0e27 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -49,6 +49,10 @@ enum FilamentType { ftPLA, ftABS, ftPET, ftHIPS, ftFLEX, ftSCAFF, ftEDGE, ftNGEN, ftPVA }; +enum DenseInfillAlgo { + dfaAutomatic, dfaEnlarged, +}; + template<> inline t_config_enum_values& ConfigOptionEnum::get_enum_values() { static t_config_enum_values keys_map; if (keys_map.empty()) { @@ -136,6 +140,15 @@ template<> inline t_config_enum_values& ConfigOptionEnum::get_enum return keys_map; } +template<> inline t_config_enum_values& ConfigOptionEnum::get_enum_values() { + static t_config_enum_values keys_map; + if (keys_map.empty()) { + keys_map["automatic"] = dfaAutomatic; + keys_map["enlarged"] = dfaEnlarged; + } + return keys_map; +} + // Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs. // Does not store the actual values, but defines default values. class PrintConfigDef : public ConfigDef @@ -429,7 +442,8 @@ public: ConfigOptionInt infill_every_layers; ConfigOptionFloatOrPercent infill_overlap; ConfigOptionFloat infill_speed; - ConfigOptionBool infill_dense; + ConfigOptionBool infill_dense; + ConfigOptionEnum infill_dense_algo; ConfigOptionBool infill_first; ConfigOptionBool overhangs; ConfigOptionBool no_perimeter_unsupported; @@ -480,6 +494,7 @@ protected: OPT_PTR(infill_overlap); OPT_PTR(infill_speed); OPT_PTR(infill_dense); + OPT_PTR(infill_dense_algo); OPT_PTR(infill_first); OPT_PTR(overhangs); OPT_PTR(no_perimeter_unsupported); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index f23af7bb2..6566c262b 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -203,6 +203,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector sparse area then fill all with dense - // sparse area = layer's fill area - dense area - const float COEFF_SPLIT = 1; + // sparse area = layer's fill area - solid area + const float COEFF_SPLIT = 2; const int NB_DENSE_LAYERS = 1; for (int idx_region = 0; idx_region < this->_print->regions.size(); ++idx_region) { //count how many surface there are on each one @@ -528,39 +529,27 @@ void PrintObject::count_distance_solid() { for (Surface &upp : previousOne->fill_surfaces.surfaces) { // i'm using intersection_ex because the result different than // upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon) - ExPolygons intersect = intersection_ex(sparse_polys, ExPolygons() = { upp.expolygon }, true); + ExPolygons intersect = intersection_ex(sparse_polys, offset_ex(upp.expolygon, -layerm->flow(frInfill).scaled_width()), true); if (!intersect.empty()) { - double area_intersect = 0; - for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area(); - //like intersect.empty() but more resilient - if (area_intersect > layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2){ + if (layerm->region()->config.infill_dense_algo == dfaEnlarged) { uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1); - if (dist <= NB_DENSE_LAYERS) { + const int nb_dense_layers = 1; + if (dist <= nb_dense_layers) { // it will be a dense infill, split the surface if needed - //if the not-dense is too big to do a full dense and the current surface isn't a dense one yet. + uint64_t area_intersect = 0; + for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area(); + //if it's in a dense area and the current surface isn't a dense one yet and the not-dense is too small. if (surf.area() > area_intersect * COEFF_SPLIT && - surf.maxNbSolidLayersOnTop > NB_DENSE_LAYERS) { + surf.maxNbSolidLayersOnTop > nb_dense_layers) { //split in two if (dist == 1) { //if just under the solid area, we can expand a bit - ExPolygons cover_intersect; - for (ExPolygon &expoly_tocover : intersect) { - ExPolygons temp = (fit_to_size(expoly_tocover, expoly_tocover, - diff_ex(offset_ex(layerm->fill_no_overlap_expolygons, layerm->flow(frInfill).scaled_width()), - offset_ex(layerm->fill_no_overlap_expolygons, -layerm->flow(frInfill).scaled_width())), - surf.expolygon, - 4 * layerm->flow(frInfill).scaled_width(), 0.01)); - cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end()); - } - intersect = offset2_ex(cover_intersect, - -layerm->flow(frInfill).scaled_width(), - layerm->flow(frInfill).scaled_width());// +scale_(expandby)); - //layerm->region()->config.external_infill_margin)); - } - else { + //remove too small sections and grew a bit to anchor it into the part + intersect = offset_ex(intersect, + layerm->flow(frInfill).scaled_width() + scale_(layerm->region()->config.bridged_infill_margin)); + } else { //just remove too small sections - intersect = offset2_ex(intersect, - -layerm->flow(frInfill).scaled_width(), + intersect = offset_ex(intersect, layerm->flow(frInfill).scaled_width()); } if (!intersect.empty()) { @@ -575,15 +564,63 @@ void PrintObject::count_distance_solid() { dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end()); dense_dist = std::min(dense_dist, dist); } + } else { + surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist); } - else { - if (area_intersect < layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) - surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist); - } - } - else { + } else { surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist); } + } else if (layerm->region()->config.infill_dense_algo == dfaAutomatic) { + double area_intersect = 0; + for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area(); + //like intersect.empty() but more resilient + if (area_intersect > layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) { + uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1); + if (dist <= NB_DENSE_LAYERS) { + // it will be a dense infill, split the surface if needed + //if the not-dense is too big to do a full dense and the current surface isn't a dense one yet. + if (surf.area() > area_intersect * COEFF_SPLIT && + surf.maxNbSolidLayersOnTop > NB_DENSE_LAYERS) { + //split in two + if (dist == 1) { + //if just under the solid area, we can expand a bit + ExPolygons cover_intersect; + for (ExPolygon &expoly_tocover : intersect) { + ExPolygons temp = (fit_to_size(expoly_tocover, expoly_tocover, + diff_ex(offset_ex(layerm->fill_no_overlap_expolygons, layerm->flow(frInfill).scaled_width()), + offset_ex(layerm->fill_no_overlap_expolygons, -layerm->flow(frInfill).scaled_width())), + surf.expolygon, + 4 * layerm->flow(frInfill).scaled_width(), 0.01)); + cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end()); + } + intersect = offset_ex(cover_intersect, + layerm->flow(frInfill).scaled_width());// +scale_(expandby)); + //layerm->region()->config.external_infill_margin)); + } else { + //just remove too small sections + intersect = offset_ex(intersect, + layerm->flow(frInfill).scaled_width()); + } + if (!intersect.empty()) { + ExPolygons sparse_surfaces = offset2_ex( + diff_ex(sparse_polys, intersect, true), + -layerm->flow(frInfill).scaled_width(), + layerm->flow(frInfill).scaled_width()); + ExPolygons dense_surfaces = diff_ex(sparse_polys, sparse_surfaces, true); + //assign (copy) + sparse_polys.clear(); + sparse_polys.insert(sparse_polys.begin(), sparse_surfaces.begin(), sparse_surfaces.end()); + dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end()); + dense_dist = std::min(dense_dist, dist); + } + } else { + if (area_intersect < layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) + surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist); + } + } else { + surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist); + } + } } } } diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index 3cff5fa4c..846e26c45 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -590,9 +590,11 @@ boost::any& Choice::get_value() else if (m_opt_id.compare("support_material_pattern") == 0) m_value = static_cast(ret_enum); else if (m_opt_id.compare("seam_position") == 0) - m_value = static_cast(ret_enum); - else if (m_opt_id.compare("host_type") == 0) - m_value = static_cast(ret_enum); + m_value = static_cast(ret_enum); + else if (m_opt_id.compare("host_type") == 0) + m_value = static_cast(ret_enum); + else if (m_opt_id.compare("infill_dense_algo") == 0) + m_value = static_cast(ret_enum); } return m_value; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 367d81492..1897416d9 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -605,7 +605,9 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt else if (opt_key.compare("seam_position") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("host_type") == 0) - config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); + else if (opt_key.compare("infill_dense_algo") == 0) + config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); } break; case coPoints:{ diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 72b94bdc1..4c4595517 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -465,6 +465,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config else if (opt_key.compare("host_type") == 0){ ret = static_cast(config.option>(opt_key)->value); } + else if (opt_key.compare("infill_dense_algo") == 0){ + ret = static_cast(config.option>(opt_key)->value); + } } break; case coPoints: diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 0b195d367..a9d695d4d 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -306,7 +306,8 @@ const std::vector& Preset::print_options() "elefant_foot_compensation", "xy_size_compensation", "hole_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", "single_extruder_multi_material_priming", "compatible_printers", "compatible_printers_condition", "inherits", - "infill_dense", "no_perimeter_unsupported", "min_perimeter_unsupported", "noperi_bridge_only", "support_material_solid_first_layer" + "infill_dense", "infill_dense_algo", "no_perimeter_unsupported", "min_perimeter_unsupported", "noperi_bridge_only", + "support_material_solid_first_layer" }; return s_opts; } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index fd5674ff6..b2d608aa5 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -833,7 +833,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"); - optgroup->append_single_option_line("infill_dense"); + line = { _(L("Suporting dense layer")), "" }; + line.append_option(optgroup->get_option("infill_dense")); + line.append_option(optgroup->get_option("infill_dense_algo")); + optgroup->append_line(line); optgroup = page->new_optgroup(_(L("Advanced"))); optgroup->append_single_option_line("solid_infill_every_layers"); @@ -1172,12 +1175,20 @@ void TabPrint::update() for (auto el : { "min_perimeter_unsupported", "noperi_bridge_only" }) get_field(el)->toggle(have_no_perimeter_unsupported); + bool have_infill = m_config->option("fill_density")->value > 0; // infill_extruder uses the same logic as in Print::extruders() for (auto el : {"fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" }) get_field(el)->toggle(have_infill); + bool can_have_infill_dense = m_config->option("fill_density")->value < 50; + for (auto el : { "infill_dense" }) + get_field(el)->toggle(can_have_infill_dense); + bool have_infill_dense = m_config->opt_bool("infill_dense") && can_have_infill_dense; + for (auto el : { "infill_dense_algo" }) + get_field(el)->toggle(have_infill_dense); + bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0; // solid_infill_extruder uses the same logic as in Print::extruders() for (auto el : {"top_fill_pattern", "bottom_fill_pattern", "enforce_full_fill_volume", "external_infill_margin", "infill_first",