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"));