From 940800b05942321a2fcacf34aa3f32ca1dc2d72e Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Tue, 29 Apr 2025 22:19:30 +0800 Subject: [PATCH] Merge tiny cracks that is part of a large bottom surface into bottom surface (#9332) * Merge tiny cracks that is part of a large bottom surface into bottom surface (SoftFever/OrcaSlicer#9329) * Revert bottom offset * Top surfaces will have perimeters around, which need to be removed from bottom surfaces so bridges not extended to visible areas --- src/libslic3r/PrintObject.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 0ca12c6860..5b53ac07b1 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1309,8 +1309,7 @@ void PrintObject::detect_surfaces_type() Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr; Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr; // collapse very narrow parts (using the safety offset in the diff is not enough) - const float offset_top = layerm->flow(frExternalPerimeter).scaled_width() / 10.f; - const float offset_bottom = layerm->flow(frExternalPerimeter).scaled_width(); + const float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f; ExPolygons layerm_slices_surfaces = to_expolygons(layerm->slices.surfaces); // no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to slice, that's why we need to start from the result of PerimeterGenerator. @@ -1325,7 +1324,7 @@ void PrintObject::detect_surfaces_type() ExPolygons upper_slices = interface_shells ? diff_ex(layerm_slices_surfaces, upper_layer->m_regions[region_id]->slices.surfaces, ApplySafetyOffset::Yes) : diff_ex(layerm_slices_surfaces, upper_layer->lslices, ApplySafetyOffset::Yes); - surfaces_append(top, opening_ex(upper_slices, offset_top), stTop); + surfaces_append(top, opening_ex(upper_slices, offset), stTop); } else { // if no upper layer, all surfaces of this one are solid // we clone surfaces because we're going to clear the slices collection @@ -1351,7 +1350,7 @@ void PrintObject::detect_surfaces_type() bottom, opening_ex( diff_ex(layerm_slices_surfaces, lower_layer->lslices, ApplySafetyOffset::Yes), - offset_bottom), + offset), surface_type_bottom_other); // if user requested internal shells, we need to identify surfaces // lying on other slices not belonging to this region @@ -1365,7 +1364,7 @@ void PrintObject::detect_surfaces_type() intersection(layerm_slices_surfaces, lower_layer->lslices), // supported lower_layer->m_regions[region_id]->slices.surfaces, ApplySafetyOffset::Yes), - offset_bottom), + offset), stBottom); } #endif @@ -1383,14 +1382,22 @@ void PrintObject::detect_surfaces_type() if (! top.empty() && ! bottom.empty()) { const auto cracks = intersection_ex(top, bottom); if (!cracks.empty()) { - const float small_crack_threshold = -offset_bottom; + const float small_crack_threshold = -layerm->flow(frExternalPerimeter).scaled_width() * 1.5; for (const auto& crack : cracks) { if (offset_ex(crack, small_crack_threshold).empty()) { + // For small cracks, if it's part of a large bottom surface, then it should be added to bottom as well + if (std::any_of(bottom.begin(), bottom.end(), [&crack, small_crack_threshold](const Surface& s) { + const auto& se = s.expolygon; + return diff_ex(crack, se, ApplySafetyOffset::Yes).empty() + && se.area() > crack.area() * 2 + && !offset_ex(diff_ex(se, crack), small_crack_threshold).empty(); + })) continue; + // Crack too small, leave it as part of the top surface, remove it from bottom surfaces Surfaces bot_tmp; for (auto& b : bottom) { - surfaces_append(bot_tmp, diff_ex(b.expolygon, crack), b.surface_type); + surfaces_append(bot_tmp, diff_ex(b.expolygon, offset_ex(crack, -small_crack_threshold)), b.surface_type); } bottom = std::move(bot_tmp); }