From c185e0805fe1f5021bce9ecee4cf6be97b2e31e2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 7 Mar 2024 16:14:46 +0800 Subject: [PATCH] ENH: improve the support of blade-shape overhangs 1. reduce the gap between blade-shape overhang and support github: #3667 2. improve sharp tail detection of blade-shape overhangs by introducing lslices_extrudable. github: #2786, #3367 jira: STUDIO-5065, STUDIO-6038 Change-Id: I4e899eace1aa28b100a6f4ce2b8d740c317f5530 (cherry picked from commit 08328b848e39c345b6c7b64021d1e0f04df24d08) (cherry picked from commit 22056d5f7e7bef5574b53fc0453781cd365bf0e1) --- src/libslic3r/Layer.hpp | 3 +- src/libslic3r/Support/SupportMaterial.cpp | 16 +++---- src/libslic3r/Support/TreeSupport.cpp | 56 +++++++++++------------ 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 45f185c4258..b9be3f3d8eb 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -139,7 +139,7 @@ class Layer // BBS mutable ExPolygons sharp_tails; mutable ExPolygons cantilevers; - mutable std::map sharp_tails_height; + mutable std::vector sharp_tails_height; // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry // (with possibly differing extruder ID and slicing parameters) and merged. @@ -150,6 +150,7 @@ class Layer // These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important // that the 1st lslice is not compensated by the Elephant foot compensation algorithm. ExPolygons lslices; + ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support std::vector lslices_bboxes; // BBS diff --git a/src/libslic3r/Support/SupportMaterial.cpp b/src/libslic3r/Support/SupportMaterial.cpp index cbf331fd785..57567b90d80 100644 --- a/src/libslic3r/Support/SupportMaterial.cpp +++ b/src/libslic3r/Support/SupportMaterial.cpp @@ -1412,6 +1412,7 @@ static inline ExPolygons detect_overhangs( const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value); const bool bridge_no_support = object_config.bridge_no_support.value; const coordf_t xy_expansion = scale_(object_config.support_expansion.value); + float lower_layer_offset = 0; if (layer_id == 0) { @@ -1424,7 +1425,7 @@ static inline ExPolygons detect_overhangs( !(bbox_size.x() > length_thresh_well_supported && bbox_size.y() > length_thresh_well_supported)) { layer.sharp_tails.push_back(slice); - layer.sharp_tails_height.insert({ &slice, layer.height }); + layer.sharp_tails_height.push_back(layer.height); } } } @@ -1444,7 +1445,6 @@ static inline ExPolygons detect_overhangs( } } - float lower_layer_offset = 0; for (LayerRegion *layerm : layer.regions()) { // Extrusion width accounts for the roundings of the extrudates. // It is the maximum widh of the extrudate. @@ -1506,7 +1506,7 @@ static inline ExPolygons detect_overhangs( 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 }); + layer.sharp_tails_height.push_back(accum_height); overhang = offset_ex(overhang, 0.05 * fw); polygons_append(diff_polygons, to_polygons(overhang)); } @@ -1546,7 +1546,7 @@ static inline ExPolygons detect_overhangs( if (layer.lower_layer) { for (ExPolygon& poly : overhang_areas) { float fw = float(layer.regions().front()->flow(frExternalPerimeter).scaled_width()); - auto cluster_boundary_ex = intersection_ex(poly, offset_ex(layer.lower_layer->lslices, scale_(0.5))); + auto cluster_boundary_ex = intersection_ex(poly, offset_ex(layer.lower_layer->lslices, std::max(fw, lower_layer_offset) + scale_(0.1))); Polygons cluster_boundary = to_polygons(cluster_boundary_ex); if (cluster_boundary.empty()) continue; double dist_max = 0; @@ -2216,9 +2216,9 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers( } // 2.3 check whether sharp tail exceed the max 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; + for (size_t i = 0; i < lower_layer_sharptails_height.size();i++) { + if (lower_layer_sharptails[i].overlaps(expoly)) { + accum_height += lower_layer_sharptails_height[i]; break; } } @@ -2243,7 +2243,7 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers( if (is_sharp_tail) { ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices); layer->sharp_tails.push_back(expoly); - layer->sharp_tails_height.insert({ &expoly, accum_height }); + layer->sharp_tails_height.push_back( accum_height ); append(overhangs_per_layers[layer_nr], overhang); #ifdef SUPPORT_TREE_DEBUG_TO_SVG SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), object.bounding_box()); diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index fe1ad5f0535..cf7634814d6 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -752,6 +752,17 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) max_cantilever_dist = 0; m_highest_overhang_layer = 0; + // calc the extrudable expolygons of each layer + 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++) { + if (m_object->print()->canceled()) + break; + Layer* layer = m_object->get_layer(layer_nr); + // Filter out areas whose diameter that is smaller than extrusion_width, but we don't want to lose any details. + layer->lslices_extrudable = intersection_ex(layer->lslices, offset2_ex(layer->lslices, -extrusion_width_scaled / 2, extrusion_width_scaled)); + } + }); // main part of overhang detection can be parallel tbb::parallel_for(tbb::blocked_range(0, m_object->layer_count()), [&](const tbb::blocked_range& range) { @@ -770,7 +781,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) 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.insert({ &slice, layer->height }); + layer->sharp_tails_height.push_back(layer->height); } } continue; @@ -780,21 +791,8 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) coordf_t lower_layer_offset = layer_nr < enforce_support_layers ? -0.15 * extrusion_width : (float)lower_layer->height / tan(threshold_rad); //lower_layer_offset = std::min(lower_layer_offset, extrusion_width); coordf_t support_offset_scaled = scale_(lower_layer_offset); - // Filter out areas whose diameter that is smaller than extrusion_width. Do not use offset2() for this purpose! - ExPolygons lower_polys; - for (const ExPolygon& expoly : lower_layer->lslices) { - if (!offset_ex(expoly, -extrusion_width_scaled / 2).empty()) { - lower_polys.emplace_back(expoly); - } - } - 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); - } - } + ExPolygons& curr_polys = layer->lslices_extrudable; + ExPolygons& lower_polys = lower_layer->lslices_extrudable; // normal overhang ExPolygons lower_layer_offseted = offset_ex(lower_polys, support_offset_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS); @@ -803,24 +801,24 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) if (is_auto(stype) && g_config_support_sharp_tails) { // BBS detect sharp tail - for (const ExPolygon* expoly : curr_poly_ptrs) { + for (const ExPolygon& expoly : curr_polys) { bool is_sharp_tail = false; // 1. nothing below // this is a sharp tail region if it's floating and non-ignorable - if (!overlaps(offset_ex(*expoly, 0.5 * extrusion_width_scaled), lower_polys)) { - is_sharp_tail = !offset_ex(*expoly, -0.1 * extrusion_width_scaled).empty(); + if (!overlaps(offset_ex(expoly, 0.5 * extrusion_width_scaled), lower_polys)) { + is_sharp_tail = !offset_ex(expoly, -0.1 * extrusion_width_scaled).empty(); } if (is_sharp_tail) { - ExPolygons overhang = diff_ex({ *expoly }, lower_polys); - 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.push_back(layer->height); append(overhang_areas, overhang); if (!overhang.empty()) { has_sharp_tails = true; #ifdef SUPPORT_TREE_DEBUG_TO_SVG - SVG::export_expolygons(debug_out_path("sharp_tail_orig_%.02f.svg", layer->print_z), { expoly }); + SVG::export_expolygons(debug_out_path("sharp_tail_orig_%.02f.svg", layer->print_z), { expoly }); #endif } } @@ -834,7 +832,7 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) // check cantilever { // lower_layer_offset may be very small, so we need to do max and then add 0.1 - auto cluster_boundary_ex = intersection_ex(poly, offset_ex(lower_layer->lslices, scale_(std::max(extrusion_width,lower_layer_offset)+0.1))); + auto cluster_boundary_ex = intersection_ex(poly, offset_ex(lower_polys, scale_(std::max(extrusion_width,lower_layer_offset)+0.1))); Polygons cluster_boundary = to_polygons(cluster_boundary_ex); if (cluster_boundary.empty()) continue; double dist_max = 0; @@ -877,7 +875,7 @@ 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) { + for (ExPolygon& expoly : layer->lslices_extrudable) { bool is_sharp_tail = false; float accum_height = layer->height; do { @@ -907,9 +905,9 @@ void TreeSupport::detect_overhangs(bool check_support_necessity/* = false*/) } // 2.3 check whether sharp tail exceed the max 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; + for(size_t i=0;ilslices); layer->sharp_tails.push_back(expoly); - layer->sharp_tails_height.insert({ &expoly, accum_height }); + layer->sharp_tails_height.push_back( accum_height); append(ts_layer->overhang_areas, overhang); if (!overhang.empty())