From 18e839e98d8ea456214a48a5565bb4746f997c3e Mon Sep 17 00:00:00 2001 From: "jiaxi.chen" Date: Thu, 15 May 2025 14:57:41 +0800 Subject: [PATCH] FIX: enforcers are covered by 'remove small overhangs' jira: STUDIO-12218 Change-Id: I6306fdf0fdb0787b2382d3667b8110e9479469c6 --- src/libslic3r/Support/TreeSupport.cpp | 73 +++++++++++++++++++-------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index f0057a02a..45623a51a 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -876,11 +876,23 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) std::chrono::time_point t0{ clock_::now() }; // main part of overhang detection can be parallel tbb::concurrent_vector overhangs_all_layers(m_object->layer_count()); + auto enforcers = m_object->slice_support_enforcers(); auto blockers = m_object->slice_support_blockers(); m_vertical_enforcer_points.clear(); m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers); m_object->project_and_append_custom_facets(false, EnforcerBlockerType::ENFORCER, enforcers, &m_vertical_enforcer_points); + auto trim_tail_empty = [](auto &vec) { + auto rit = std::find_if(vec.rbegin(), vec.rend(), [](const auto &e) { return !e.empty(); }); + if (rit != vec.rend()) { + vec.erase(rit.base(), vec.end()); + } else { + vec.clear(); + } + }; + trim_tail_empty(enforcers); + trim_tail_empty(blockers); + tbb::parallel_for(tbb::blocked_range(0, m_object->layer_count()), [&](const tbb::blocked_range& range) { for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++) { @@ -1132,6 +1144,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) for (auto &cluster : overhangClusters) { + bool enforce_add = false; // remove small overhangs if (is_auto(stype) && config_remove_small_overhangs) { // 3. check whether the small overhang is sharp tail @@ -1143,6 +1156,16 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) break; } } + if (!enforcers.empty() && cluster.min_layer= enforcers.size()) break; + if (enforcers[layer_id].empty()) continue; + if (overlaps(to_expolygons(enforcers[layer_id]), cluster.layer_overhangs[layer_id])) { + enforce_add = true; + break; + } + } + } cluster.check_small_overhang(extrusion_width_scaled, length_thresh_small_overhang, radius_thresh_small_overhang); @@ -1158,11 +1181,15 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) #endif } - if (!cluster.is_type(Small)) { + if (!cluster.is_type(Small) || enforce_add) { cluster.check_polygon_node(m_support_params.thresh_big_overhang, m_ts_data->m_layer_outlines_below[cluster.min_layer - 1]); for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) { int layer_nr = it->first; ExPolygons overhangs = it->second; + if (cluster.is_type(Small)) { + if (layer_nr >= enforcers.size() || enforcers[layer_nr].empty() || !overlaps(to_expolygons(enforcers[layer_nr]), overhangs)) continue; + overhangs = intersection_ex(overhangs, enforcers[layer_nr]); + } for (const auto &overhang : overhangs) add_overhang(m_object->get_layer(layer_nr), overhang, cluster.type); } } @@ -1181,42 +1208,47 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) if (lower_layer == nullptr || enforcers.empty() || layer_nr >= enforcers.size() || enforcers[layer_nr].empty()) { layer->loverhangs.clear(); layer->loverhangs_with_type.clear(); + for (const auto &cantilever : layer->cantilevers) add_overhang(layer, cantilever, OverhangType::Cantilever); } else { - ExPolygons enforced_overhangs = intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]); - ExPolygons loverhangs_new; + ExPolygons enforced_overhangs = to_expolygons(enforcers[layer_nr]); + ExPolygons loverhangs_new; std::vector> loverhangs_with_type_new; - if (!enforced_overhangs.empty()) { - for (auto &overhang_part : layer->loverhangs_with_type) { - const auto &overhang = overhang_part.first; - auto type = overhang_part.second; - if (type & OverhangType::Cantilever || type & OverhangType::SharpTail) continue; - if (!overlaps(enforced_overhangs, overhang)) continue; - ExPolygons overhangs = intersection_ex(enforced_overhangs, overhang); - if (!overhangs.empty()) { + ExPolygons bigflat; + for (auto &overhang_part : layer->loverhangs_with_type) { + const auto &overhang = overhang_part.first; + auto type = overhang_part.second; + ExPolygons overhangs; + if (type & OverhangType::Cantilever || type & OverhangType::SharpTail) + overhangs = {overhang}; + else if (overlaps(enforced_overhangs, overhang)) { + overhangs = intersection_ex(enforced_overhangs, overhang); + } + if (!overhangs.empty()) { + if (type & OverhangType::BigFlat) + append(bigflat, overhangs); + else for (const auto &expoly : overhangs) { loverhangs_new.emplace_back(expoly); loverhangs_with_type_new.emplace_back(std::make_pair(expoly, type)); } - } } } - layer->loverhangs = std::move(loverhangs_new); + for (const auto &expoly : union_ex(bigflat)) { + loverhangs_new.emplace_back(expoly); + loverhangs_with_type_new.emplace_back(std::make_pair(expoly, OverhangType::BigFlat)); + } + layer->loverhangs = std::move(loverhangs_new); layer->loverhangs_with_type = std::move(loverhangs_with_type_new); } - for (auto &cantilever : layer->cantilevers) add_overhang(layer, cantilever, OverhangType::Cantilever); } // add support for every 1mm height for sharp tails - ExPolygons sharp_tail_overhangs; - if (lower_layer == nullptr) - sharp_tail_overhangs = layer->sharp_tails; - else { + if (lower_layer){ ExPolygons lower_layer_expanded = offset_ex(lower_layer->lslices_extrudable, SCALED_RESOLUTION); for (size_t i = 0; i < layer->sharp_tails_height.size();i++) { ExPolygons areas = diff_clipped({ layer->sharp_tails[i]}, lower_layer_expanded); float accum_height = layer->sharp_tails_height[i]; if (!areas.empty() && int(accum_height * 10) % 5 == 0) { - append(sharp_tail_overhangs, areas); has_sharp_tails = true; for (auto &area : areas) add_overhang(layer, area, accum_height < EPSILON ? (OverhangType::SharpTail | OverhangType::SharpTailLowesst) : OverhangType::SharpTail); @@ -1235,9 +1267,6 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) int nDetected = layer->loverhangs.size(); - //// add sharp tail overhangs - //append(layer->loverhangs, sharp_tail_overhangs); - //// fill overhang_types //for (size_t i = 0; i < layer->loverhangs.size(); i++) // overhang_types.emplace(&layer->loverhangs[i], i < nDetected ? OverhangType::Detected :