From 56af1162576943c1657e1185b447db141d2a57f1 Mon Sep 17 00:00:00 2001 From: supermerill Date: Sat, 20 Nov 2021 01:59:54 +0100 Subject: [PATCH] Dense infill: fix the full fill density bug & rework detection settings: * AutoNotFull: now print the dense infill only if the area to cover doesn't fill the sparse area. * AutoOrEnlarged: now print the auto dense infill, unless the area to cover is wider than (nozzle diameter*2/infill ratio) and the enlarged version is smaller than the auto * New: AutoOrDisable: now print the auto dense infill, unless the area to cover is wider than (nozzle diameter*2/infill ratio) or the area to cover fill the sparse area. --- src/libslic3r/Fill/Fill.cpp | 1 + src/libslic3r/PrintConfig.cpp | 2 + src/libslic3r/PrintConfig.hpp | 10 +++- src/libslic3r/PrintObject.cpp | 105 ++++++++++++++++++++++++---------- 4 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index aa1b38d76..fbc88fcd2 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -146,6 +146,7 @@ std::vector group_fills(const Layer &layer) is_bridge = true; params.pattern = ipRectiWithPerimeter; params.priority = surface.priority; + params.dont_adjust = true; // keep the 42% density params.connection = InfillConnection::icConnected; } if (params.density <= 0 && !is_denser) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 32c89872e..72ebde98b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2350,10 +2350,12 @@ void PrintConfigDef::init_fff_params() " The Anchored option just slightly enlarges (by 'Default infill margin') the surfaces that need a better support."); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("automatic"); + def->enum_values.push_back("autonotfull"); def->enum_values.push_back("autosmall"); def->enum_values.push_back("autoenlarged"); def->enum_values.push_back("enlarged"); def->enum_labels.push_back(L("Automatic")); + def->enum_labels.push_back(L("Automatic, unless full")); def->enum_labels.push_back(L("Automatic, only for small areas")); def->enum_labels.push_back(L("Automatic, or anchored if too big")); def->enum_labels.push_back(L("Anchored")); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 32537c609..8d5047e62 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -121,7 +121,12 @@ enum SLAMaterial { slamHeatResistant, }; enum DenseInfillAlgo { - dfaAutomatic, dfaAutoNotFull, dfaAutoOrEnlarged , dfaEnlarged, + dfaAutomatic, + dfaAutoNotFull, + dfaAutoOrEnlarged, + dfaAutoOrNothing, + dfaEnlarged, + dfaDisabled, }; enum NoPerimeterUnsupportedAlgo { @@ -313,8 +318,9 @@ template<> inline const t_config_enum_values& ConfigOptionEnum::ge template<> inline const t_config_enum_values& ConfigOptionEnum::get_enum_values() { static const t_config_enum_values keys_map = { { "automatic", dfaAutomatic }, - { "autosmall", dfaAutoNotFull }, + { "autonotfull", dfaAutoNotFull }, { "autoenlarged", dfaAutoOrEnlarged }, + { "autosmall", dfaAutoOrNothing}, { "enlarged", dfaEnlarged } }; return keys_map; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 3fbe51b3b..8e8a725dc 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1193,7 +1193,7 @@ namespace Slic3r { ExPolygons dense_polys; std::vector dense_priority; const ExPolygons surfs_with_overlap = { surface.expolygon }; - ////create a surface with overlap to allow the dense thing to bond to the infill + // create a surface with overlap to allow the dense thing to bond to the infill coord_t scaled_width = layerm->flow(frInfill, true).scaled_width(); coord_t overlap = scaled_width / 4; for (const ExPolygon& surf_with_overlap : surfs_with_overlap) { @@ -1203,46 +1203,89 @@ namespace Slic3r { if (upp.has_fill_solid()) { // i'm using intersection_ex because the result different than // upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon) - //and a little offset2 to remove the almost supported area + // and a little offset2 to remove the almost supported area ExPolygons intersect = offset2_ex( intersection_ex(sparse_polys, { upp.expolygon }, true) , (float)-layerm->flow(frInfill).scaled_width(), (float)layerm->flow(frInfill).scaled_width()); if (!intersect.empty()) { - double area_intersect = 0; - // calculate area to decide if area is small enough for autofill - if (layerm->region()->config().infill_dense_algo.value == dfaAutoNotFull || layerm->region()->config().infill_dense_algo.value == dfaAutoOrEnlarged) - for (ExPolygon poly_inter : intersect) - area_intersect += poly_inter.area(); + DenseInfillAlgo algo = layerm->region()->config().infill_dense_algo.value; - double surf_with_overlap_area = surf_with_overlap.area(); - if (layerm->region()->config().infill_dense_algo.value == dfaEnlarged - || (layerm->region()->config().infill_dense_algo.value == dfaAutoOrEnlarged && surf_with_overlap_area <= area_intersect * COEFF_SPLIT)) { + //if no infill, don't bother, it's always yes + if (region->config().fill_density.value == 0) { + if (dfaAutoOrEnlarged == algo) + algo = dfaAutomatic; + else if (dfaAutomatic != algo) + algo = dfaAutoNotFull; + } + if ( dfaAutoOrNothing == algo + || dfaAutoOrEnlarged == algo) { + //check if small enough + double max_nozzle_diam = 0; + for (uint16_t extruder_id : object_extruders()) { + max_nozzle_diam = std::max(max_nozzle_diam, print()->config().nozzle_diameter.values[extruder_id]); + } + coordf_t min_width = scale_d(max_nozzle_diam) / region->config().fill_density.get_abs_value(1.); + ExPolygons smalls = offset_ex(intersect, -min_width); + //small enough ? + if (smalls.empty()) { + if (dfaAutoOrNothing == algo) + algo = dfaAutoNotFull; + if (dfaAutoOrEnlarged == algo) + algo = dfaAutomatic; + } else if (dfaAutoOrNothing == algo) { + algo = dfaDisabled; + } + } + if (dfaEnlarged == algo) { //expand the area a bit intersect = offset_ex(intersect, (scaled(layerm->region()->config().external_infill_margin.get_abs_value( region->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (region->config().perimeters - 1)))))); - } else if (layerm->region()->config().infill_dense_algo.value == dfaAutoNotFull - || layerm->region()->config().infill_dense_algo.value == dfaAutomatic) { - - //like intersect.empty() but more resilient - if (layerm->region()->config().infill_dense_algo.value == dfaAutomatic - || surf_with_overlap_area > area_intersect * COEFF_SPLIT) { - ExPolygons cover_intersect; - - // it will be a dense infill, split the surface if needed - //ExPolygons cover_intersect; - for (ExPolygon& expoly_tocover : intersect) { - ExPolygons temp = dense_fill_fit_to_size( - expoly_tocover, - surf_with_overlap, - 4 * layerm->flow(frInfill).scaled_width(), - 0.01f); - cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end()); - } - intersect = cover_intersect; - } else { - intersect.clear(); + intersect = intersection_ex(intersect, sparse_polys); + } else if (dfaDisabled == algo) { + intersect.clear(); + } else { + double sparse_area = surf_with_overlap.area(); + double area_to_cover = 0; + double min_area_to_cover = 0; + if (dfaAutoNotFull == algo) { + // calculate area to decide if area is small enough for autofill + for (ExPolygon poly_inter : intersect) + area_to_cover += poly_inter.area(); + // if we have to fill everything, don't bother + if (area_to_cover * 1.1 > sparse_area) + intersect.clear(); } + //like intersect.empty() but more resilient + ExPolygons cover_intersect; + + // it will be a dense infill, split the surface if needed + //ExPolygons cover_intersect; + for (ExPolygon& expoly_tocover : intersect) { + ExPolygons temp = dense_fill_fit_to_size( + expoly_tocover, + surf_with_overlap, + 4 * layerm->flow(frInfill).scaled_width(), + 0.01f); + cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end()); + } + // calculate area to decide if area is small enough for autofill + if (dfaAutoOrEnlarged == algo) { + double area_dense_covered = 0; + for (ExPolygon poly_inter : cover_intersect) + area_dense_covered += poly_inter.area(); + // if enlarge is smaller, use enlarge + intersect = offset_ex(intersect, (scaled(layerm->region()->config().external_infill_margin.get_abs_value( + region->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (region->config().perimeters - 1)))))); + intersect = intersection_ex(intersect, sparse_polys); + double area_enlarged_covered = 0; + for (ExPolygon poly_inter : intersect) + area_enlarged_covered += poly_inter.area(); + if (area_dense_covered < area_enlarged_covered) { + intersect = cover_intersect; + } + }else + intersect = cover_intersect; } if (!intersect.empty()) {