FIX: enforcers are covered by 'remove small overhangs'

jira: STUDIO-12218
Change-Id: I6306fdf0fdb0787b2382d3667b8110e9479469c6
This commit is contained in:
jiaxi.chen 2025-05-15 14:57:41 +08:00 committed by lane.wei
parent 6a12adb7f0
commit 18e839e98d

View File

@ -876,11 +876,23 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
std::chrono::time_point<clock_> t0{ clock_::now() }; std::chrono::time_point<clock_> t0{ clock_::now() };
// main part of overhang detection can be parallel // main part of overhang detection can be parallel
tbb::concurrent_vector<ExPolygons> overhangs_all_layers(m_object->layer_count()); tbb::concurrent_vector<ExPolygons> overhangs_all_layers(m_object->layer_count());
auto enforcers = m_object->slice_support_enforcers(); auto enforcers = m_object->slice_support_enforcers();
auto blockers = m_object->slice_support_blockers(); auto blockers = m_object->slice_support_blockers();
m_vertical_enforcer_points.clear(); 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::BLOCKER, blockers);
m_object->project_and_append_custom_facets(false, EnforcerBlockerType::ENFORCER, enforcers, &m_vertical_enforcer_points); 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<size_t>(0, m_object->layer_count()), tbb::parallel_for(tbb::blocked_range<size_t>(0, m_object->layer_count()),
[&](const tbb::blocked_range<size_t>& range) { [&](const tbb::blocked_range<size_t>& range) {
for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++) { 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) { for (auto &cluster : overhangClusters) {
bool enforce_add = false;
// remove small overhangs // remove small overhangs
if (is_auto(stype) && config_remove_small_overhangs) { if (is_auto(stype) && config_remove_small_overhangs) {
// 3. check whether the small overhang is sharp tail // 3. check whether the small overhang is sharp tail
@ -1143,6 +1156,16 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
break; break;
} }
} }
if (!enforcers.empty() && cluster.min_layer<enforcers.size()) {
for (size_t layer_id = cluster.min_layer; layer_id <= cluster.max_layer; layer_id++) {
if (layer_id >= 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); 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 #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]); 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++) { for (auto it = cluster.layer_overhangs.begin(); it != cluster.layer_overhangs.end(); it++) {
int layer_nr = it->first; int layer_nr = it->first;
ExPolygons overhangs = it->second; 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); 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()) { if (lower_layer == nullptr || enforcers.empty() || layer_nr >= enforcers.size() || enforcers[layer_nr].empty()) {
layer->loverhangs.clear(); layer->loverhangs.clear();
layer->loverhangs_with_type.clear(); layer->loverhangs_with_type.clear();
for (const auto &cantilever : layer->cantilevers) add_overhang(layer, cantilever, OverhangType::Cantilever);
} else { } else {
ExPolygons enforced_overhangs = intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]); ExPolygons enforced_overhangs = to_expolygons(enforcers[layer_nr]);
ExPolygons loverhangs_new; ExPolygons loverhangs_new;
std::vector<std::pair<ExPolygon, int>> loverhangs_with_type_new; std::vector<std::pair<ExPolygon, int>> loverhangs_with_type_new;
if (!enforced_overhangs.empty()) { ExPolygons bigflat;
for (auto &overhang_part : layer->loverhangs_with_type) { for (auto &overhang_part : layer->loverhangs_with_type) {
const auto &overhang = overhang_part.first; const auto &overhang = overhang_part.first;
auto type = overhang_part.second; auto type = overhang_part.second;
if (type & OverhangType::Cantilever || type & OverhangType::SharpTail) continue; ExPolygons overhangs;
if (!overlaps(enforced_overhangs, overhang)) continue; if (type & OverhangType::Cantilever || type & OverhangType::SharpTail)
ExPolygons overhangs = intersection_ex(enforced_overhangs, overhang); overhangs = {overhang};
if (!overhangs.empty()) { 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) { for (const auto &expoly : overhangs) {
loverhangs_new.emplace_back(expoly); loverhangs_new.emplace_back(expoly);
loverhangs_with_type_new.emplace_back(std::make_pair(expoly, type)); 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); 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 // add support for every 1mm height for sharp tails
ExPolygons sharp_tail_overhangs; if (lower_layer){
if (lower_layer == nullptr)
sharp_tail_overhangs = layer->sharp_tails;
else {
ExPolygons lower_layer_expanded = offset_ex(lower_layer->lslices_extrudable, SCALED_RESOLUTION); ExPolygons lower_layer_expanded = offset_ex(lower_layer->lslices_extrudable, SCALED_RESOLUTION);
for (size_t i = 0; i < layer->sharp_tails_height.size();i++) { for (size_t i = 0; i < layer->sharp_tails_height.size();i++) {
ExPolygons areas = diff_clipped({ layer->sharp_tails[i]}, lower_layer_expanded); ExPolygons areas = diff_clipped({ layer->sharp_tails[i]}, lower_layer_expanded);
float accum_height = layer->sharp_tails_height[i]; float accum_height = layer->sharp_tails_height[i];
if (!areas.empty() && int(accum_height * 10) % 5 == 0) { if (!areas.empty() && int(accum_height * 10) % 5 == 0) {
append(sharp_tail_overhangs, areas);
has_sharp_tails = true; has_sharp_tails = true;
for (auto &area : areas) for (auto &area : areas)
add_overhang(layer, area, accum_height < EPSILON ? (OverhangType::SharpTail | OverhangType::SharpTailLowesst) : OverhangType::SharpTail); 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(); int nDetected = layer->loverhangs.size();
//// add sharp tail overhangs
//append(layer->loverhangs, sharp_tail_overhangs);
//// fill overhang_types //// fill overhang_types
//for (size_t i = 0; i < layer->loverhangs.size(); i++) //for (size_t i = 0; i < layer->loverhangs.size(); i++)
// overhang_types.emplace(&layer->loverhangs[i], i < nDetected ? OverhangType::Detected : // overhang_types.emplace(&layer->loverhangs[i], i < nDetected ? OverhangType::Detected :