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
This commit is contained in:
Arthur 2022-09-22 11:09:38 +08:00 committed by Lane.Wei
parent 5152a90545
commit abddb1edc3
9 changed files with 60 additions and 38 deletions

View File

@ -125,6 +125,7 @@ public:
// BBS // BBS
mutable ExPolygons sharp_tails; mutable ExPolygons sharp_tails;
mutable ExPolygons cantilevers;
mutable std::map<const ExPolygon*, float> sharp_tails_height; mutable std::map<const ExPolygon*, float> sharp_tails_height;
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry

View File

@ -666,7 +666,7 @@ static std::vector<std::string> s_Preset_print_options {
//"independent_support_layer_height", //"independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers", "support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern", "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", "filename_format", "wall_filament",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_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", "ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",

View File

@ -2168,6 +2168,14 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionBool(false)); 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. // BBS: change type to common float.
// It may be rounded to mulitple layer height when independent_support_layer_height is false. // It may be rounded to mulitple layer height when independent_support_layer_height is false.
def = this->add("support_top_z_distance", coFloat); def = this->add("support_top_z_distance", coFloat);

View File

@ -594,6 +594,7 @@ PRINT_CONFIG_CLASS_DEFINE(
// Direction of the support pattern (in XY plane).` // Direction of the support pattern (in XY plane).`
((ConfigOptionFloat, support_angle)) ((ConfigOptionFloat, support_angle))
((ConfigOptionBool, support_on_build_plate_only)) ((ConfigOptionBool, support_on_build_plate_only))
((ConfigOptionBool, support_critical_regions_only))
((ConfigOptionFloat, support_top_z_distance)) ((ConfigOptionFloat, support_top_z_distance))
((ConfigOptionInt, enforce_support_layers)) ((ConfigOptionInt, enforce_support_layers))
((ConfigOptionInt, support_filament)) ((ConfigOptionInt, support_filament))

View File

@ -701,6 +701,7 @@ bool PrintObject::invalidate_state_by_config_options(
opt_key == "support_type" opt_key == "support_type"
|| opt_key == "support_angle" || opt_key == "support_angle"
|| opt_key == "support_on_build_plate_only" || opt_key == "support_on_build_plate_only"
|| opt_key == "support_critical_regions_only"
|| opt_key == "enforce_support_layers" || opt_key == "enforce_support_layers"
|| opt_key == "support_filament" || opt_key == "support_filament"
|| opt_key == "support_line_width" || opt_key == "support_line_width"

View File

@ -673,6 +673,7 @@ void TreeSupport::detect_object_overhangs()
const coordf_t extrusion_width_scaled = scale_(extrusion_width); const coordf_t extrusion_width_scaled = scale_(extrusion_width);
const coordf_t max_bridge_length = scale_(config.max_bridge_length.value); 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 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 int enforce_support_layers = config.enforce_support_layers.value;
const double area_thresh_well_supported = SQ(scale_(6)); // min: 6x6=36mm^2 const double area_thresh_well_supported = SQ(scale_(6)); // min: 6x6=36mm^2
const double length_thresh_well_supported = scale_(6); // min: 6mm const double length_thresh_well_supported = scale_(6); // min: 6mm
@ -694,6 +695,7 @@ void TreeSupport::detect_object_overhangs()
int min_layer = 1e7; int min_layer = 1e7;
int max_layer = 0; int max_layer = 0;
coordf_t offset = 0; coordf_t offset = 0;
bool is_cantilever = false;
OverhangCluster(const ExPolygon* expoly, int layer_nr) { OverhangCluster(const ExPolygon* expoly, int layer_nr) {
push_back(expoly, layer_nr); push_back(expoly, layer_nr);
} }
@ -822,8 +824,11 @@ void TreeSupport::detect_object_overhangs()
// normal overhang // normal overhang
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS); 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)); 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 = 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.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; ExPolygons overhangs_sharp_tail;
if (is_auto && g_config_support_sharp_tails) 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); overhang_areas = union_ex(overhang_areas, overhangs_sharp_tail);
} }
#else #else
// BBS // BBS detect sharp tail
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails; const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
for (ExPolygon& expoly : layer->lslices) { 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); TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
for (ExPolygon& poly : overhang_areas) { 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()) if (!offset_ex(poly, -0.1 * extrusion_width_scaled).empty())
ts_layer->overhang_areas.emplace_back(poly); ts_layer->overhang_areas.emplace_back(poly);
#endif
} }
if (is_auto && g_config_remove_small_overhangs) { 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::ENFORCER, enforcers);
m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers); 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<double>::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 (is_auto && g_config_remove_small_overhangs) {
if (blockers.size() < m_object->layer_count()) if (blockers.size() < m_object->layer_count())
blockers.resize(m_object->layer_count()); blockers.resize(m_object->layer_count());
@ -1045,25 +1067,8 @@ void TreeSupport::detect_object_overhangs()
} }
if (is_sharp_tail) continue; if (is_sharp_tail) continue;
// 4. check whether the overhang cluster is cantilever (far awary from main body) // 4. check whether the overhang cluster is cantilever
Layer* layer = m_object->get_layer(cluster.min_layer); if (cluster.is_cantilever) continue;
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<double>::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;
for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) { for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) {
int layer_nr = it->first; int layer_nr = it->first;
@ -1088,6 +1093,11 @@ void TreeSupport::detect_object_overhangs()
break; break;
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers); 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()) { if (layer_nr < blockers.size()) {
Polygons& blocker = blockers[layer_nr]; Polygons& blocker = blockers[layer_nr];

View File

@ -510,7 +510,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers", "support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
"bridge_no_support", "thick_bridges", "max_bridge_length", "support_top_z_distance", "bridge_no_support", "thick_bridges", "max_bridge_length", "support_top_z_distance",
//BBS: add more support params to dependent of enable_support //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"}) "support_object_xy_distance", "independent_support_layer_height"})
toggle_field(el, have_support_material); toggle_field(el, have_support_material);
toggle_field("support_threshold_angle", have_support_material && (support_type == stNormalAuto || support_type == stTreeAuto || support_type==stHybridAuto)); toggle_field("support_threshold_angle", have_support_material && (support_type == stNormalAuto || support_type == stTreeAuto || support_type==stHybridAuto));

View File

@ -55,7 +55,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF =
{ L("Infill") , { "sparse_infill_density", "sparse_infill_pattern" } }, { L("Infill") , { "sparse_infill_density", "sparse_infill_pattern" } },
// BBS // BBS
{ L("Support") , { "enable_support", "support_type", "support_threshold_angle", { 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" } } "support_base_pattern_spacing" } }
//BBS //BBS
//{ L("Wipe options") , { "flush_into_infill", "flush_into_objects" } } //{ L("Wipe options") , { "flush_into_infill", "flush_into_objects" } }
@ -81,7 +81,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
{"tree_support_branch_angle", "",10}, {"tree_support_wall_count", "",11},{"tree_support_with_infill", "",12},//tree support {"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_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_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} { L("Speed"), {{"support_speed", "",12}, {"support_interface_speed", "",13}
}} }}
@ -138,7 +138,7 @@ std::vector<SimpleSettingData> SettingsFactory::get_visible_options(const std::s
//Quality //Quality
"layer_height", "initial_layer_print_height", "adaptive_layer_height", "seam_position", "xy_hole_compensation", "xy_contour_compensation", "elefant_foot_compensation", "support_line_width", "layer_height", "initial_layer_print_height", "adaptive_layer_height", "seam_position", "xy_hole_compensation", "xy_contour_compensation", "elefant_foot_compensation", "support_line_width",
//Support //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
"tree_support_wall_count", "tree_support_with_infill", "tree_support_wall_count", "tree_support_with_infill",
//support //support

View File

@ -1853,6 +1853,7 @@ void TabPrint::build()
optgroup->append_single_option_line("support_type", "support#support-types"); 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_threshold_angle", "support#threshold-angle");
optgroup->append_single_option_line("support_on_build_plate_only"); 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->append_single_option_line("enforce_support_layers");
optgroup = page->new_optgroup(L("Support filament")); optgroup = page->new_optgroup(L("Support filament"));