diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 6d95d4e943..bbaa7e6c97 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4809,7 +4809,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloatOrPercent(50., true)); def = this->add("tree_support_branch_angle", coFloat); - def->label = L("Tree support branch angle"); + def->label = L("Branch angle"); def->category = L("Support"); def->tooltip = L("This setting determines the maximum overhang angle that t he branches of tree support allowed to make." "If the angle is increased, the branches can be printed more horizontally, allowing them to reach farther."); @@ -4843,7 +4843,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloat(25)); def = this->add("tree_support_branch_distance", coFloat); - def->label = L("Tree support branch distance"); + def->label = L("Branch distance"); def->category = L("Support"); def->tooltip = L("This setting determines the distance between neighboring tree support nodes."); def->sidetext = L("mm"); @@ -4907,7 +4907,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloat(0.8)); def = this->add("tree_support_branch_diameter", coFloat); - def->label = L("Tree support branch diameter"); + def->label = L("Branch diameter"); def->category = L("Support"); def->tooltip = L("This setting determines the initial diameter of support nodes."); def->sidetext = L("mm"); @@ -4916,16 +4916,6 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(5.)); - def = this->add("tree_support_branch_diameter_organic", coFloat); - def->label = L("Tree support branch diameter"); - def->category = L("Support"); - def->tooltip = L("This setting determines the initial diameter of support nodes."); - def->sidetext = L("mm"); - def->min = 1.0; - def->max = 10; - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloat(2.)); - def = this->add("tree_support_branch_diameter_angle", coFloat); // TRN PrintSettings: #lmFIXME def->label = L("Branch Diameter Angle"); @@ -4940,6 +4930,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(5)); + def = this->add("tree_support_branch_diameter_organic", coFloat); + def->label = L("Tree support branch diameter"); + def->category = L("Support"); + def->tooltip = L("This setting determines the initial diameter of support nodes."); + def->sidetext = L("mm"); + def->min = 1.0; + def->max = 10; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(2.)); + def = this->add("tree_support_wall_count", coInt); def->label = L("Support wall loops"); def->category = L("Support"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index d7d4dd5087..06778e1ad1 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -842,8 +842,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, tree_support_branch_distance)) ((ConfigOptionFloat, tree_support_tip_diameter)) ((ConfigOptionFloat, tree_support_branch_diameter)) - ((ConfigOptionFloat, tree_support_branch_diameter_angle)) ((ConfigOptionFloat, tree_support_branch_angle)) + ((ConfigOptionFloat, tree_support_branch_diameter_angle)) ((ConfigOptionFloat, tree_support_angle_slow)) ((ConfigOptionInt, tree_support_wall_count)) ((ConfigOptionBool, tree_support_adaptive_layer_height)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index a2deed0924..9f1fbdc1e2 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -733,7 +733,8 @@ void PrintObject::simplify_extrusion_path() } if (this->set_started(posSimplifySupportPath)) { - //BBS: share same progress + //BBS: disable circle simplification for support as it causes separation of support walls + #if 0 m_print->set_status(75, L("Optimizing toolpath")); BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - start"; tbb::parallel_for( @@ -747,6 +748,7 @@ void PrintObject::simplify_extrusion_path() ); m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Simplify extrusion path of support in parallel - end"; + #endif this->set_done(posSimplifySupportPath); } } @@ -3680,91 +3682,8 @@ template void PrintObject::remove_bridges_from_contacts( SupportNecessaryType PrintObject::is_support_necessary() { - static const double super_overhang_area_threshold = SQ(scale_(5.0)); const double cantilevel_dist_thresh = scale_(6); -#if 0 - double threshold_rad = (m_config.support_threshold_angle.value < EPSILON ? 30 : m_config.support_threshold_angle.value + 1) * M_PI / 180.; - int enforce_support_layers = m_config.enforce_support_layers; - // not fixing in extrusion width % PR b/c never called - const coordf_t extrusion_width = m_config.line_width.value; - const coordf_t extrusion_width_scaled = scale_(extrusion_width); - float max_bridge_length = scale_(m_config.max_bridge_length.value); - const bool bridge_no_support = max_bridge_length > 0;// config.bridge_no_support.value; - for (size_t layer_nr = enforce_support_layers + 1; layer_nr < this->layer_count(); layer_nr++) { - Layer* layer = m_layers[layer_nr]; - Layer* lower_layer = layer->lower_layer; - - coordf_t support_offset_scaled = extrusion_width_scaled * 0.9; - ExPolygons lower_layer_offseted = offset_ex(lower_layer->lslices, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS); - - // 1. check sharp tail - for (const LayerRegion* layerm : layer->regions()) { - for (const ExPolygon& expoly : layerm->raw_slices) { - // detect sharp tail - if (intersection_ex({ expoly }, lower_layer_offseted).empty()) - return SharpTail; - } - } - - // 2. check overhang area - ExPolygons super_overhang_expolys = std::move(diff_ex(layer->lslices, lower_layer_offseted)); - super_overhang_expolys.erase(std::remove_if( - super_overhang_expolys.begin(), - super_overhang_expolys.end(), - [extrusion_width_scaled](ExPolygon& area) { - return offset_ex(area, -0.1 * extrusion_width_scaled).empty(); - }), - super_overhang_expolys.end()); - - // remove bridge - if (bridge_no_support) - remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &super_overhang_expolys, max_bridge_length); - - Polygons super_overhang_polys = to_polygons(super_overhang_expolys); - - - super_overhang_polys.erase(std::remove_if( - super_overhang_polys.begin(), - super_overhang_polys.end(), - [extrusion_width_scaled](Polygon& area) { - return offset_ex(area, -0.1 * extrusion_width_scaled).empty(); - }), - super_overhang_polys.end()); - - double super_overhang_area = 0.0; - for (Polygon& poly : super_overhang_polys) { - bool is_ccw = poly.is_counter_clockwise(); - double area_ = poly.area(); - if (is_ccw) { - if (area_ > super_overhang_area_threshold) - return LargeOverhang; - super_overhang_area += area_; - } - else { - super_overhang_area -= area_; - } - } - - //if (super_overhang_area > super_overhang_area_threshold) - // return LargeOverhang; - - // 3. check overhang distance - const double distance_threshold_scaled = extrusion_width_scaled * 2; - ExPolygons lower_layer_offseted_2 = offset_ex(lower_layer->lslices, distance_threshold_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS); - ExPolygons exceed_overhang = std::move(diff_ex(super_overhang_polys, lower_layer_offseted_2)); - exceed_overhang.erase(std::remove_if( - exceed_overhang.begin(), - exceed_overhang.end(), - [extrusion_width_scaled](ExPolygon& area) { - // tolerance for 1 extrusion width offset - return offset_ex(area, -0.5 * extrusion_width_scaled).empty(); - }), - exceed_overhang.end()); - if (!exceed_overhang.empty()) - return LargeOverhang; - } -#else TreeSupport tree_support(*this, m_slicing_params); tree_support.support_type = SupportType::stTreeAuto; // need to set support type to fully utilize the power of feature detection tree_support.detect_overhangs(true); @@ -3773,7 +3692,7 @@ SupportNecessaryType PrintObject::is_support_necessary() return SharpTail; else if (tree_support.has_cantilever && tree_support.max_cantilever_dist > cantilevel_dist_thresh) return Cantilever; -#endif + return NoNeedSupp; } diff --git a/src/libslic3r/Support/SupportCommon.cpp b/src/libslic3r/Support/SupportCommon.cpp index 7651b1c71b..f4611a175f 100644 --- a/src/libslic3r/Support/SupportCommon.cpp +++ b/src/libslic3r/Support/SupportCommon.cpp @@ -1417,6 +1417,10 @@ SupportGeneratorLayersPtr generate_support_layers( append(layers_sorted, intermediate_layers); append(layers_sorted, interface_layers); append(layers_sorted, base_interface_layers); + // remove dupliated layers + std::sort(layers_sorted.begin(), layers_sorted.end()); + layers_sorted.erase(std::unique(layers_sorted.begin(), layers_sorted.end()), layers_sorted.end()); + // Sort the layers lexicographically by a raising print_z and a decreasing height. std::sort(layers_sorted.begin(), layers_sorted.end(), [](auto *l1, auto *l2) { return *l1 < *l2; }); int layer_id = 0; @@ -1648,7 +1652,7 @@ void generate_support_toolpaths( { SupportLayer &support_layer = *support_layers[support_layer_id]; LayerCache &layer_cache = layer_caches[support_layer_id]; - const float support_interface_angle = support_params.support_style == smsGrid ? + const float support_interface_angle = (support_params.support_style == smsGrid || config.support_interface_pattern == smipRectilinear) ? support_params.interface_angle : support_params.raft_interface_angle(support_layer.interface_id()); // Find polygons with the same print_z. @@ -1785,7 +1789,7 @@ void generate_support_toolpaths( // Base support or flange. if (! base_layer.empty() && ! base_layer.polygons_to_extrude().empty()) { - Fill *filler = filler_support.get(); + Fill *filler = filler_support.get(); filler->angle = angles[support_layer_id % angles.size()]; // We don't use $base_flow->spacing because we need a constant spacing // value that guarantees that all layers are correctly aligned. @@ -1811,7 +1815,11 @@ void generate_support_toolpaths( sheath = true; no_sort = true; } else if (support_params.support_style == SupportMaterialStyle::smsTreeOrganic) { - tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params); + // if the tree supports are too tall, use double wall to make it stronger + SupportParameters support_params2 = support_params; + if (support_layer.print_z > 100.0) + support_params2.tree_branch_diameter_double_wall_area_scaled = 0.1; + tree_supports_generate_paths(base_layer.extrusions, base_layer.polygons_to_extrude(), flow, support_params2); done = true; } if (! done) diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index 9f5457d2f8..efbb3b8191 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -1540,7 +1540,10 @@ void TreeSupport::generate_toolpaths() erSupportMaterial, filler_support.get(), support_density); } else { - tree_supports_generate_paths(ts_layer->support_fills.entities, loops, flow, m_support_params); + SupportParameters support_params = m_support_params; + if (area_group.need_extra_wall && object_config.tree_support_wall_count.value == 0) + support_params.tree_branch_diameter_double_wall_area_scaled = 0.1; + tree_supports_generate_paths(ts_layer->support_fills.entities, loops, flow, support_params); } } } @@ -2917,6 +2920,10 @@ void TreeSupport::smooth_nodes() } float max_move = scale_(m_object_config->support_line_width / 2); + // if the branch is very tall, the tip also needs extra wall + float thresh_tall_branch = 100; + float thresh_dist_to_top = 30; + for (int layer_nr = 0; layer_nr< contact_nodes.size(); layer_nr++) { std::vector &curr_layer_nodes = contact_nodes[layer_nr]; if (curr_layer_nodes.empty()) continue; @@ -2926,17 +2933,20 @@ void TreeSupport::smooth_nodes() std::vector radii; std::vector branch; SupportNode * p_node = node; + float total_height = 0; // add a fixed head if it's not a polygon node, see STUDIO-4403 // Polygon node can't be added because the move distance might be huge, making the nodes in between jump and dangling if (node->child && node->child->type!=ePolygon) { pts.push_back(p_node->child->position); radii.push_back(p_node->child->radius); branch.push_back(p_node->child); + total_height += p_node->child->height; } do { pts.push_back(p_node->position); radii.push_back(p_node->radius); branch.push_back(p_node); + total_height += p_node->height; p_node = p_node->parent; } while (p_node && !p_node->is_processed); if (pts.size() < 3) continue; @@ -2955,7 +2965,8 @@ void TreeSupport::smooth_nodes() branch[i]->radius = radii1[i]; branch[i]->movement = (pts[i + 1] - pts[i - 1]) / 2; branch[i]->is_processed = true; - if (branch[i]->parents.size()>1 || (branch[i]->movement.x() > max_move || branch[i]->movement.y() > max_move)) + if (branch[i]->parents.size() > 1 || (branch[i]->movement.x() > max_move || branch[i]->movement.y() > max_move) || + (total_height > thresh_tall_branch && branch[i]->dist_mm_to_top < thresh_dist_to_top)) branch[i]->need_extra_wall = true; BOOST_LOG_TRIVIAL(info) << "smooth_nodes: layer_nr=" << layer_nr << ", i=" << i << ", pt=" << pt << ", movement=" << branch[i]->movement << ", radius=" << branch[i]->radius; } diff --git a/src/libslic3r/Support/TreeSupport3D.cpp b/src/libslic3r/Support/TreeSupport3D.cpp index dad831076c..8b8acd7b57 100644 --- a/src/libslic3r/Support/TreeSupport3D.cpp +++ b/src/libslic3r/Support/TreeSupport3D.cpp @@ -36,6 +36,7 @@ #include #include +#include #if defined(TREE_SUPPORT_SHOW_ERRORS) && defined(_WIN32) #define TREE_SUPPORT_SHOW_ERRORS_WIN32 @@ -3551,7 +3552,9 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons print.set_status(69, _L("Generating support")); generate_support_toolpaths(print_object.support_layers(), print_object.config(), support_params, print_object.slicing_parameters(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers); - + + auto t_end = std::chrono::high_resolution_clock::now(); + BOOST_LOG_TRIVIAL(info) << "Total time of organic tree support: " << 0.001 * std::chrono::duration_cast(t_end - t_start).count() << " ms"; #if 0 //#ifdef SLIC3R_DEBUG { diff --git a/src/libslic3r/Support/TreeSupportCommon.hpp b/src/libslic3r/Support/TreeSupportCommon.hpp index 3122a43d2d..31e410838d 100644 --- a/src/libslic3r/Support/TreeSupportCommon.hpp +++ b/src/libslic3r/Support/TreeSupportCommon.hpp @@ -87,7 +87,7 @@ struct TreeSupportMeshGroupSettings { this->support_tree_angle = std::clamp(config.tree_support_branch_angle_organic * M_PI / 180., 0., 0.5 * M_PI - EPSILON); this->support_tree_angle_slow = std::clamp(config.tree_support_angle_slow * M_PI / 180., 0., this->support_tree_angle - EPSILON); this->support_tree_branch_diameter = scaled(config.tree_support_branch_diameter_organic.value); - this->support_tree_branch_diameter_angle = std::clamp(config.tree_support_branch_diameter_angle * M_PI / 180., 0., 0.5 * M_PI - EPSILON); + this->support_tree_branch_diameter_angle = std::clamp(config.tree_support_branch_diameter_angle * M_PI / 180., 0., 0.5 * M_PI - EPSILON); this->support_tree_top_rate = config.tree_support_top_rate.value; // percent // this->support_tree_tip_diameter = this->support_line_width; this->support_tree_tip_diameter = std::clamp(scaled(config.tree_support_tip_diameter.value), (coord_t)0, this->support_tree_branch_diameter); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 096a83a512..f3861c69aa 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -90,7 +90,7 @@ std::map> SettingsFactory::OBJECT_C { L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3}, {"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6}, {"support_threshold_overlap", "",6}, {"support_on_build_plate_only", "",7}, {"support_filament", "",8},{"support_interface_filament", "",9},{"support_expansion", "",24},{"support_style", "",25}, - {"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10},{"tree_support_branch_angle_organic","",10}, {"tree_support_wall_count", "",11},//tree support + {"tree_support_brim_width", "",26}, {"tree_support_branch_angle", "",10},{"tree_support_branch_angle_organic","",10}, {"tree_support_wall_count", "",11},{"tree_support_branch_diameter_angle", "",11},//tree support {"support_top_z_distance", "",13},{"support_bottom_z_distance", "",12},{"support_base_pattern", "",14},{"support_base_pattern_spacing", "",15}, {"support_interface_top_layers", "",16},{"support_interface_bottom_layers", "",17},{"support_interface_spacing", "",18},{"support_bottom_interface_spacing", "",19}, {"support_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23},{"support_remove_small_overhang","",27}, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9e0b5eb8a5..9abcbfb2de 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2228,7 +2228,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_object_xy_distance", "support"); optgroup->append_single_option_line("support_object_first_layer_gap", "support"); optgroup->append_single_option_line("bridge_no_support", "support#base-pattern"); - optgroup->append_single_option_line("max_bridge_length", "support#base-pattern"); + optgroup->append_single_option_line("max_bridge_length", "support#tree-support-only-options"); optgroup->append_single_option_line("independent_support_layer_height", "support"); optgroup = page->new_optgroup(L("Tree supports"), L"param_support_tree");