From 55a1141e67a9f9934c37670a6d0881a7774176d8 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 11 May 2023 17:45:33 +0800 Subject: [PATCH] FIX: sharp tail detection misses some sharp tails 1. Previously if there are multiple sharp tails in a layer, some will be missed. To fix this, we should not skip if the current layer is already detected as sharp tails. 2. Do not mistakenly detect sharp horns as sharp tails by only detecting the overhang areas larger than half of the extrusion line width. Github: #1578 Jira: STUDIO-2659 Change-Id: If7ba5c9ae547d3051551aa6fa34eb6214d01a46d --- src/libslic3r/SupportMaterial.cpp | 46 +++++++++++++++---------------- src/libslic3r/TreeSupport.cpp | 45 ++++++++++++++++-------------- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 05542694b..da76ea2f4 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -1634,25 +1634,28 @@ static inline ExPolygons detect_overhangs( //FIXME add user defined filtering here based on minimal area or minimum radius or whatever. // BBS - for (ExPolygon& expoly : layerm->raw_slices) { - bool is_sharp_tail = false; - float accum_height = layer.height; + if (g_config_support_sharp_tails) { + for (ExPolygon& expoly : layerm->raw_slices) { + if (offset_ex(expoly, -0.5 * fw).empty()) continue; + bool is_sharp_tail = false; + float accum_height = layer.height; - // 1. nothing below - // Check whether this is a sharp tail region. - // Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body. - if (g_config_support_sharp_tails && !overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) { - is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.1*fw).empty(); - } + // 1. nothing below + // Check whether this is a sharp tail region. + // Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body. + if (!overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) { + is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * fw).empty(); + } - if (is_sharp_tail) { - ExPolygons overhang = diff_ex({ expoly }, lower_layer_polygons); - layer.sharp_tails.push_back(expoly); - layer.sharp_tails_height.insert({ &expoly, accum_height }); - overhang = offset_ex(overhang, 0.05 * fw); - polygons_append(diff_polygons, to_polygons(overhang)); + if (is_sharp_tail) { + ExPolygons overhang = diff_ex({ expoly }, lower_layer_expolys); + layer.sharp_tails.push_back(expoly); + layer.sharp_tails_height.insert({ &expoly, accum_height }); + overhang = offset_ex(overhang, 0.05 * fw); + polygons_append(diff_polygons, to_polygons(overhang)); + } } - } + } } if (diff_polygons.empty()) @@ -2269,15 +2272,12 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ const Layer* layer = object.get_layer(layer_nr); const Layer* lower_layer = layer->lower_layer; - // skip if: - // 1) if the current layer is already detected as sharp tails - // 2) lower layer has no sharp tails - if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true) + if (!lower_layer) continue; // BBS detect sharp tail const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails; - auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; + const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; for (const ExPolygon& expoly : layer->lslices) { bool is_sharp_tail = false; float accum_height = layer->height; @@ -2308,13 +2308,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ } // 2.3 check whether sharp tail exceed the max height - for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) { + for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) { if (lower_sharp_tail_height.first->overlaps(expoly)) { accum_height += lower_sharp_tail_height.second; break; } } - if (accum_height >= sharp_tail_max_support_height) { + if (accum_height > sharp_tail_max_support_height) { is_sharp_tail = false; break; } diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index 78c5012b5..5c680ba72 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -864,9 +864,11 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) } } ExPolygons curr_polys; + std::vector curr_poly_ptrs; for (const ExPolygon& expoly : layer->lslices) { if (!offset_ex(expoly, -extrusion_width_scaled / 2).empty()) { curr_polys.emplace_back(expoly); + curr_poly_ptrs.emplace_back(&expoly); } } @@ -879,28 +881,30 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) overhang_areas.end()); - ExPolygons overhangs_sharp_tail; if (is_auto(stype) && g_config_support_sharp_tails) { // 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) { + for (const ExPolygon* expoly : curr_poly_ptrs) { bool is_sharp_tail = false; // 1. nothing below // this is a sharp tail region if it's small but non-ignorable - if (!overlaps(offset_ex(expoly, 0.5 * extrusion_width_scaled), lower_polys)) { - is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * extrusion_width_scaled).empty(); + if (!overlaps(offset_ex(*expoly, 0.5 * extrusion_width_scaled), lower_polys)) { + is_sharp_tail = expoly->area() < area_thresh_well_supported && !offset_ex(*expoly, -0.1 * extrusion_width_scaled).empty(); } if (is_sharp_tail) { - ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices); - layer->sharp_tails.push_back(expoly); - layer->sharp_tails_height.insert({ &expoly, layer->height }); + ExPolygons overhang = diff_ex({ *expoly }, lower_polys); + layer->sharp_tails.push_back(*expoly); + layer->sharp_tails_height.insert({ expoly, layer->height }); append(overhang_areas, overhang); - if (!overhang.empty()) + if (!overhang.empty()) { has_sharp_tails = true; +#ifdef SUPPORT_TREE_DEBUG_TO_SVG + SVG svg(format("SVG/sharp_tail_orig_%.02f.svg", layer->print_z), m_object->bounding_box()); + if (svg.is_opened()) svg.draw(overhang, "red"); +#endif + } } } } @@ -947,15 +951,12 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) Layer* layer = m_object->get_layer(layer_nr); SupportLayer* ts_layer = m_object->get_support_layer(layer_nr + m_raft_layers); Layer* lower_layer = layer->lower_layer; - // skip if: - // 1) if the current layer is already detected as sharp tails - // 2) lower layer has no sharp tails - if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true) + if (!lower_layer) continue; // BBS detect sharp tail const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails; - auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; + const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height; for (ExPolygon& expoly : layer->lslices) { bool is_sharp_tail = false; float accum_height = layer->height; @@ -986,13 +987,13 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) } // 2.3 check whether sharp tail exceed the max height - for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) { + for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) { if (lower_sharp_tail_height.first->overlaps(expoly)) { accum_height += lower_sharp_tail_height.second; break; } } - if (accum_height >= sharp_tail_max_support_height) { + if (accum_height > sharp_tail_max_support_height) { is_sharp_tail = false; break; } @@ -1018,8 +1019,8 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) if (!overhang.empty()) has_sharp_tails = true; #ifdef SUPPORT_TREE_DEBUG_TO_SVG - SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), m_object->bounding_box()); - if (svg.is_opened()) svg.draw(overhang, "yellow"); + SVG svg(format("SVG/sharp_tail_%.02f.svg",layer->print_z), m_object->bounding_box()); + if (svg.is_opened()) svg.draw(overhang, "red"); #endif } @@ -1068,10 +1069,14 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only) const Layer* layer1 = m_object->get_layer(cluster.min_layer); BoundingBox bbox = cluster.merged_bbox; bbox.merge(get_extents(layer1->lslices)); - SVG svg(format("SVG/overhangCluster_%s_%s_tail=%s_cantilever=%s_small=%s.svg", cluster.min_layer, layer1->print_z, cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang), bbox); + SVG svg(format("SVG/overhangCluster_%s-%s_%s-%s_tail=%s_cantilever=%s_small=%s.svg", + cluster.min_layer, cluster.max_layer, layer1->print_z, m_object->get_layer(cluster.max_layer)->print_z, + cluster.is_sharp_tail, cluster.is_cantilever, cluster.is_small_overhang), bbox); if (svg.is_opened()) { svg.draw(layer1->lslices, "red"); svg.draw(cluster.merged_poly, "blue"); + svg.draw_text(bbox.min + Point(scale_(0), scale_(2)), "lslices", "red", 2); + svg.draw_text(bbox.min + Point(scale_(0), scale_(2)), "overhang", "blue", 2); } #endif