From abddb1edc30b8d46f4f8c10e153d1e8b85a594a4 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 22 Sep 2022 11:09:38 +0800 Subject: [PATCH] NEW: add support_critical_regions_only for tree support When this option enabled, only generate supports for sharp tail, cantilever, thin pillar (not well supported). So holes are safe from unnessary supports. Currently only works for tree supports, will need to copied to normal supports if it works fine. Change-Id: I5eb86484a5b503149e3bfdee8ce73f76a0a849e4 --- src/libslic3r/Layer.hpp | 1 + src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 8 +++ src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/PrintObject.cpp | 1 + src/libslic3r/TreeSupport.cpp | 76 +++++++++++++++------------ src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/GUI_Factories.cpp | 6 +-- src/slic3r/GUI/Tab.cpp | 1 + 9 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 414619788..8e01f599b 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -125,6 +125,7 @@ public: // BBS mutable ExPolygons sharp_tails; + mutable ExPolygons cantilevers; mutable std::map sharp_tails_height; // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 9b4ea8347..40e3331dc 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -666,7 +666,7 @@ static std::vector s_Preset_print_options { //"independent_support_layer_height", "support_angle", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern", - "support_top_z_distance", "support_on_build_plate_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence", + "support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence", "filename_format", "wall_filament", "sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament", "ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ccfc3807f..b73157460 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2168,6 +2168,14 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionBool(false)); + // BBS + def = this->add("support_critical_regions_only", coBool); + def->label = L("Support critical regions only"); + def->category = L("Support"); + def->tooltip = L("Only create support for critical regions including sharp tail, cantilever, etc."); + def->mode = comSimple; + def->set_default_value(new ConfigOptionBool(false)); + // BBS: change type to common float. // It may be rounded to mulitple layer height when independent_support_layer_height is false. def = this->add("support_top_z_distance", coFloat); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 76e3ecc21..cebf28e8d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -594,6 +594,7 @@ PRINT_CONFIG_CLASS_DEFINE( // Direction of the support pattern (in XY plane).` ((ConfigOptionFloat, support_angle)) ((ConfigOptionBool, support_on_build_plate_only)) + ((ConfigOptionBool, support_critical_regions_only)) ((ConfigOptionFloat, support_top_z_distance)) ((ConfigOptionInt, enforce_support_layers)) ((ConfigOptionInt, support_filament)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index f99c9cb3a..8806a5b15 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -701,6 +701,7 @@ bool PrintObject::invalidate_state_by_config_options( opt_key == "support_type" || opt_key == "support_angle" || opt_key == "support_on_build_plate_only" + || opt_key == "support_critical_regions_only" || opt_key == "enforce_support_layers" || opt_key == "support_filament" || opt_key == "support_line_width" diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index c85c164b4..0f4cb81fd 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -673,6 +673,7 @@ void TreeSupport::detect_object_overhangs() const coordf_t extrusion_width_scaled = scale_(extrusion_width); const coordf_t max_bridge_length = scale_(config.max_bridge_length.value); const bool bridge_no_support = max_bridge_length > 0;// config.bridge_no_support.value; + const bool support_critical_regions_only = config.support_critical_regions_only.value; const int enforce_support_layers = config.enforce_support_layers.value; const double area_thresh_well_supported = SQ(scale_(6)); // min: 6x6=36mm^2 const double length_thresh_well_supported = scale_(6); // min: 6mm @@ -694,6 +695,7 @@ void TreeSupport::detect_object_overhangs() int min_layer = 1e7; int max_layer = 0; coordf_t offset = 0; + bool is_cantilever = false; OverhangCluster(const ExPolygon* expoly, int layer_nr) { push_back(expoly, layer_nr); } @@ -822,8 +824,11 @@ void TreeSupport::detect_object_overhangs() // normal overhang ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS); ExPolygons overhang_areas = std::move(diff_ex(curr_polys, lower_layer_offseted)); - //overhang_areas = std::move(offset2_ex(overhang_areas, -0.1 * extrusion_width_scaled, 0.1 * extrusion_width_scaled)); - overhang_areas.erase(std::remove_if(overhang_areas.begin(), overhang_areas.end(), [extrusion_width_scaled](ExPolygon& area) {return offset_ex(area, -0.1 * extrusion_width_scaled).empty(); }), overhang_areas.end()); + // overhang_areas = std::move(offset2_ex(overhang_areas, -0.1 * extrusion_width_scaled, 0.1 * extrusion_width_scaled)); + overhang_areas.erase(std::remove_if(overhang_areas.begin(), overhang_areas.end(), + [extrusion_width_scaled](ExPolygon &area) { return offset_ex(area, -0.1 * extrusion_width_scaled).empty(); }), + overhang_areas.end()); + ExPolygons overhangs_sharp_tail; if (is_auto && g_config_support_sharp_tails) @@ -854,7 +859,7 @@ void TreeSupport::detect_object_overhangs() overhang_areas = union_ex(overhang_areas, overhangs_sharp_tail); } #else - // BBS + // BBS detect sharp tail const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails; auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; for (ExPolygon& expoly : layer->lslices) { @@ -939,19 +944,8 @@ void TreeSupport::detect_object_overhangs() TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers); for (ExPolygon& poly : overhang_areas) { - // NOTE: must push something into ts_layer->overhang_areas, can't be empty for any layer, - // otherwise remove_small_overhangs can't correctly cluster overhangs -#if 0 - ExPolygons poly_simp = poly.simplify(scale_(radius_sample_resolution)); - // simplify method may delete the entire polygon which is unwanted - if(!poly_simp.empty()) - append(ts_layer->overhang_areas, poly_simp); - else - ts_layer->overhang_areas.emplace_back(poly); -#else if (!offset_ex(poly, -0.1 * extrusion_width_scaled).empty()) ts_layer->overhang_areas.emplace_back(poly); -#endif } if (is_auto && g_config_remove_small_overhangs) { @@ -1004,6 +998,34 @@ void TreeSupport::detect_object_overhangs() m_object->project_and_append_custom_facets(false, EnforcerBlockerType::ENFORCER, enforcers); m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers); + // check whether the overhang cluster is cantilever (far awary from main body) + for (auto& cluster : overhangClusters) { + Layer* layer = m_object->get_layer(cluster.min_layer); + if (layer->lower_layer == NULL) continue; + Layer* lower_layer = layer->lower_layer; + auto cluster_boundary = intersection(cluster.merged_poly, offset(lower_layer->lslices, scale_(0.5))); + double dist_max = 0; + Points cluster_pts; + for (auto& poly : cluster.merged_poly) + append(cluster_pts, poly.contour.points); + for (auto& pt : cluster_pts) { + double dist_pt = std::numeric_limits::max(); + for (auto& poly : cluster_boundary) { + double d = poly.distance_to(pt); + dist_pt = std::min(dist_pt, d); + } + dist_max = std::max(dist_max, dist_pt); + } + if (dist_max > scale_(5)) { // this cluster is cantilever, add all expolygons to sharp tail + for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) { + int layer_nr = it->first; + auto p_overhang = it->second; + m_object->get_layer(layer_nr)->cantilevers.emplace_back(*p_overhang); + } + cluster.is_cantilever = true; + } + } + if (is_auto && g_config_remove_small_overhangs) { if (blockers.size() < m_object->layer_count()) blockers.resize(m_object->layer_count()); @@ -1045,25 +1067,8 @@ void TreeSupport::detect_object_overhangs() } if (is_sharp_tail) continue; - // 4. check whether the overhang cluster is cantilever (far awary from main body) - Layer* layer = m_object->get_layer(cluster.min_layer); - if (layer->lower_layer == NULL) continue; - Layer* lower_layer = layer->lower_layer; - auto cluster_boundary = intersection(cluster.merged_poly, offset(lower_layer->lslices, scale_(0.5))); - double dist_max = 0; - Points cluster_pts; - for (auto& poly : cluster.merged_poly) - append(cluster_pts, poly.contour.points); - for (auto& pt : cluster_pts) { - double dist_pt = std::numeric_limits::max(); - for (auto& poly : cluster_boundary) { - double d = poly.distance_to(pt); - dist_pt = std::min(dist_pt, d); - } - dist_max = std::max(dist_max, dist_pt); - } - if (dist_max > scale_(5)) - continue; + // 4. check whether the overhang cluster is cantilever + if (cluster.is_cantilever) continue; for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) { int layer_nr = it->first; @@ -1088,6 +1093,11 @@ void TreeSupport::detect_object_overhangs() break; TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers); + if (support_critical_regions_only) { + auto layer = m_object->get_layer(layer_nr); + ts_layer->overhang_areas = layer->sharp_tails; + append(ts_layer->overhang_areas, layer->cantilevers); + } if (layer_nr < blockers.size()) { Polygons& blocker = blockers[layer_nr]; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 220b3d5fd..7b6e35b7f 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -510,7 +510,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co "support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers", "bridge_no_support", "thick_bridges", "max_bridge_length", "support_top_z_distance", //BBS: add more support params to dependent of enable_support - "support_type","support_on_build_plate_only", + "support_type", "support_on_build_plate_only", "support_critical_regions_only", "support_object_xy_distance", "independent_support_layer_height"}) toggle_field(el, have_support_material); toggle_field("support_threshold_angle", have_support_material && (support_type == stNormalAuto || support_type == stTreeAuto || support_type==stHybridAuto)); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 31a1a9fc1..434022788 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -55,7 +55,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF = { L("Infill") , { "sparse_infill_density", "sparse_infill_pattern" } }, // BBS { L("Support") , { "enable_support", "support_type", "support_threshold_angle", - "support_base_pattern", "support_on_build_plate_only", + "support_base_pattern", "support_on_build_plate_only","support_critical_regions_only", "support_base_pattern_spacing" } } //BBS //{ L("Wipe options") , { "flush_into_infill", "flush_into_objects" } } @@ -81,7 +81,7 @@ std::map> SettingsFactory::OBJECT_C {"tree_support_branch_angle", "",10}, {"tree_support_wall_count", "",11},{"tree_support_with_infill", "",12},//tree support {"support_top_z_distance", "",13},{"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_object_xy_distance", "",20}, {"bridge_no_support", "",21},{"max_bridge_length", "",22},{"support_critical_regions_only", "",23} }}, { L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13} }} @@ -138,7 +138,7 @@ std::vector SettingsFactory::get_visible_options(const std::s //Quality "layer_height", "initial_layer_print_height", "adaptive_layer_height", "seam_position", "xy_hole_compensation", "xy_contour_compensation", "elefant_foot_compensation", "support_line_width", //Support - "enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "enforce_support_layers", + "enable_support", "support_type", "support_threshold_angle", "support_on_build_plate_only", "support_critical_regions_only", "enforce_support_layers", //tree support "tree_support_wall_count", "tree_support_with_infill", //support diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9debf820f..38c9251c2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1853,6 +1853,7 @@ void TabPrint::build() optgroup->append_single_option_line("support_type", "support#support-types"); optgroup->append_single_option_line("support_threshold_angle", "support#threshold-angle"); optgroup->append_single_option_line("support_on_build_plate_only"); + optgroup->append_single_option_line("support_critical_regions_only"); //optgroup->append_single_option_line("enforce_support_layers"); optgroup = page->new_optgroup(L("Support filament"));