mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-09-28 14:23:13 +08:00
FIX: classify enforced support overhangs
jira: STUDIO-11484 Change-Id: I4b9e5a86b095bc788c803a22a551c6a9c1fad95e
This commit is contained in:
parent
6d2f21ef4c
commit
c03e133404
@ -876,25 +876,36 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
std::chrono::time_point<clock_> t0{ clock_::now() };
|
||||
// main part of overhang detection can be parallel
|
||||
tbb::concurrent_vector<ExPolygons> 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);
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_object->layer_count()),
|
||||
[&](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_nr = range.begin(); layer_nr < range.end(); layer_nr++) {
|
||||
if (m_object->print()->canceled())
|
||||
break;
|
||||
|
||||
if (!is_auto(stype) && layer_nr > enforce_support_layers)
|
||||
// FIXME the param enforce_support_layers is not set yet
|
||||
if (!(is_auto(stype) || (enforce_support_layers > 0 && layer_nr >= enforce_support_layers) || (layer_nr < enforcers.size() && !enforcers[layer_nr].empty())))
|
||||
continue;
|
||||
|
||||
Layer* layer = m_object->get_layer(layer_nr);
|
||||
|
||||
if (layer->lower_layer == nullptr) {
|
||||
for (auto& slice : layer->lslices_extrudable) {
|
||||
ExPolygons curr_polys = layer->lslices_extrudable;
|
||||
if (layer_nr < blockers.size() && !blockers[layer_nr].empty())
|
||||
curr_polys = diff_ex(curr_polys, offset_ex(union_(blockers[layer_nr]), scale_(radius_sample_resolution)));
|
||||
for (auto& slice : curr_polys) {
|
||||
auto bbox_size = get_extents(slice).size();
|
||||
if (!((bbox_size.x() > length_thresh_well_supported || bbox_size.y() > length_thresh_well_supported))
|
||||
&& g_config_support_sharp_tails) {
|
||||
layer->sharp_tails.push_back(slice);
|
||||
layer->sharp_tails_height.push_back(layer->height);
|
||||
}
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
SVG::export_expolygons(debug_out_path("sharp_tail_orig_%.02f.svg", layer->print_z), {slice});
|
||||
#endif
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -905,10 +916,32 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
coordf_t support_offset_scaled = scale_(lower_layer_offset);
|
||||
ExPolygons& curr_polys = layer->lslices_extrudable;
|
||||
ExPolygons& lower_polys = lower_layer->lslices_extrudable;
|
||||
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
|
||||
// normal overhang
|
||||
ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
overhangs_all_layers[layer_nr] = std::move(diff_ex(curr_polys, lower_layer_offseted));
|
||||
// add enforcer
|
||||
ExPolygons enforced_overhangs;
|
||||
ExPolygons blocker;
|
||||
if (!enforcers.empty())
|
||||
enforced_overhangs = intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]);
|
||||
if (is_auto(stype)) {
|
||||
// normal overhang
|
||||
overhangs_all_layers[layer_nr] = std::move(diff_ex(curr_polys, lower_layer_offseted));
|
||||
// if is auto, add blocker first
|
||||
if (layer_nr < blockers.size() && !blockers[layer_nr].empty()) {
|
||||
// Arthur: union_ is a must because after mirroring, the blocker polygons are in left-hand coordinates, ie clockwise,
|
||||
// which are not valid polygons, and will be removed by offset_ex. union_ can make these polygons right.
|
||||
blocker = offset_ex(union_(blockers[layer_nr]), scale_(radius_sample_resolution));
|
||||
if (!blocker.empty()) overhangs_all_layers[layer_nr] = diff_ex(overhangs_all_layers[layer_nr], blocker);
|
||||
}
|
||||
if (!enforced_overhangs.empty()) overhangs_all_layers[layer_nr] = union_ex(overhangs_all_layers[layer_nr], enforced_overhangs);
|
||||
}
|
||||
else if (layer_nr < enforcers.size() && lower_layer) {
|
||||
if (!enforced_overhangs.empty()) {
|
||||
// FIXME this is a hack to make enforcers work on steep overhangs. See STUDIO-7538.
|
||||
enforced_overhangs = diff_ex(offset_ex(enforced_overhangs, enforcer_overhang_offset), lower_layer->lslices_extrudable);
|
||||
overhangs_all_layers[layer_nr] = std::move(enforced_overhangs);
|
||||
}
|
||||
}
|
||||
|
||||
double duration{ std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
||||
if (duration > 30 || overhangs_all_layers[layer_nr].size() > 100) {
|
||||
@ -919,8 +952,11 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
}
|
||||
if (is_auto(stype) && config_detect_sharp_tails)
|
||||
{
|
||||
ExPolygons curr = curr_polys;
|
||||
if (!blocker.empty()) curr = diff_ex(curr, blocker);
|
||||
if (!enforced_overhangs.empty()) curr = union_ex(curr, enforced_overhangs);
|
||||
// BBS detect sharp tail
|
||||
for (const ExPolygon& expoly : curr_polys) {
|
||||
for (const ExPolygon& expoly : curr) {
|
||||
bool is_sharp_tail = false;
|
||||
// 1. nothing below
|
||||
// this is a sharp tail region if it's floating and non-ignorable
|
||||
@ -1015,7 +1051,13 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
// BBS detect sharp tail
|
||||
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
|
||||
const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
||||
for (ExPolygon& expoly : layer->lslices_extrudable) {
|
||||
|
||||
ExPolygons curr_polys = layer->lslices_extrudable;
|
||||
if (!blockers.empty() && layer_nr < blockers.size() && !blockers[layer_nr].empty())
|
||||
curr_polys = diff_ex(curr_polys, offset_ex(union_(blockers[layer_nr]), scale_(radius_sample_resolution)));
|
||||
if (!enforcers.empty() && layer_nr < enforcers.size() && !enforcers[layer_nr].empty())
|
||||
curr_polys = union_ex(curr_polys, intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]));
|
||||
for (ExPolygon& expoly : curr_polys) {
|
||||
bool is_sharp_tail = false;
|
||||
float accum_height = layer->height;
|
||||
do {
|
||||
@ -1088,12 +1130,6 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
}
|
||||
}
|
||||
|
||||
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::ENFORCER, enforcers, &m_vertical_enforcer_points);
|
||||
m_object->project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers);
|
||||
|
||||
|
||||
for (auto &cluster : overhangClusters) {
|
||||
// remove small overhangs
|
||||
@ -1142,8 +1178,31 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
auto lower_layer = layer->lower_layer;
|
||||
|
||||
if (support_critical_regions_only && is_auto(stype)) {
|
||||
layer->loverhangs.clear(); // remove oridinary overhangs, only keep cantilevers and sharp tails (added later)
|
||||
layer->loverhangs_with_type.clear();
|
||||
if (lower_layer == nullptr || enforcers.empty() || layer_nr >= enforcers.size() || enforcers[layer_nr].empty()) {
|
||||
layer->loverhangs.clear();
|
||||
layer->loverhangs_with_type.clear();
|
||||
} else {
|
||||
ExPolygons enforced_overhangs = intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]);
|
||||
ExPolygons loverhangs_new;
|
||||
std::vector<std::pair<ExPolygon, int>> 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()) {
|
||||
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);
|
||||
layer->loverhangs_with_type = std::move(loverhangs_with_type_new);
|
||||
}
|
||||
for (auto &cantilever : layer->cantilevers) add_overhang(layer, cantilever, OverhangType::Cantilever);
|
||||
}
|
||||
|
||||
@ -1168,19 +1227,6 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_nr < blockers.size()) {
|
||||
// Arthur: union_ is a must because after mirroring, the blocker polygons are in left-hand coordinates, ie clockwise,
|
||||
// which are not valid polygons, and will be removed by offset_ex. union_ can make these polygons right.
|
||||
ExPolygons blocker = offset_ex(union_(blockers[layer_nr]), scale_(radius_sample_resolution));
|
||||
auto old_overhangs_with_type = layer->loverhangs_with_type;
|
||||
layer->loverhangs.clear();
|
||||
layer->loverhangs_with_type.clear();
|
||||
for (auto &poly : old_overhangs_with_type) {
|
||||
ExPolygons polydiff = diff_ex(poly.first, blocker);
|
||||
for (auto &diff : polydiff) add_overhang(layer, diff, OverhangType(poly.second));
|
||||
}
|
||||
}
|
||||
|
||||
if (max_bridge_length > 0 && layer->loverhangs.size() > 0 && lower_layer) {
|
||||
// do not break bridge as the interface will be poor, see #4318
|
||||
bool break_bridge = false;
|
||||
@ -1188,16 +1234,6 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/)
|
||||
}
|
||||
|
||||
int nDetected = layer->loverhangs.size();
|
||||
// enforcers now follow same logic as normal support. See STUDIO-3692
|
||||
if (layer_nr < enforcers.size() && lower_layer) {
|
||||
ExPolygons enforced_overhangs = intersection_ex(diff_ex(layer->lslices_extrudable, lower_layer->lslices_extrudable), enforcers[layer_nr]);
|
||||
if (!enforced_overhangs.empty()) {
|
||||
// FIXME this is a hack to make enforcers work on steep overhangs. See STUDIO-7538.
|
||||
enforced_overhangs = diff_ex(offset_ex(enforced_overhangs, enforcer_overhang_offset), lower_layer->lslices_extrudable);
|
||||
for (auto &poly : enforced_overhangs) add_overhang(layer, poly, OverhangType::Normal);
|
||||
}
|
||||
}
|
||||
int nEnforced = layer->loverhangs.size();
|
||||
|
||||
//// add sharp tail overhangs
|
||||
//append(layer->loverhangs, sharp_tail_overhangs);
|
||||
|
Loading…
x
Reference in New Issue
Block a user