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.
This commit is contained in:
supermerill 2021-11-20 01:59:54 +01:00
parent a535725e5d
commit 56af116257
4 changed files with 85 additions and 33 deletions

View File

@ -146,6 +146,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
is_bridge = true; is_bridge = true;
params.pattern = ipRectiWithPerimeter; params.pattern = ipRectiWithPerimeter;
params.priority = surface.priority; params.priority = surface.priority;
params.dont_adjust = true; // keep the 42% density
params.connection = InfillConnection::icConnected; params.connection = InfillConnection::icConnected;
} }
if (params.density <= 0 && !is_denser) if (params.density <= 0 && !is_denser)

View File

@ -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."); " The Anchored option just slightly enlarges (by 'Default infill margin') the surfaces that need a better support.");
def->enum_keys_map = &ConfigOptionEnum<DenseInfillAlgo>::get_enum_values(); def->enum_keys_map = &ConfigOptionEnum<DenseInfillAlgo>::get_enum_values();
def->enum_values.push_back("automatic"); def->enum_values.push_back("automatic");
def->enum_values.push_back("autonotfull");
def->enum_values.push_back("autosmall"); def->enum_values.push_back("autosmall");
def->enum_values.push_back("autoenlarged"); def->enum_values.push_back("autoenlarged");
def->enum_values.push_back("enlarged"); def->enum_values.push_back("enlarged");
def->enum_labels.push_back(L("Automatic")); 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, only for small areas"));
def->enum_labels.push_back(L("Automatic, or anchored if too big")); def->enum_labels.push_back(L("Automatic, or anchored if too big"));
def->enum_labels.push_back(L("Anchored")); def->enum_labels.push_back(L("Anchored"));

View File

@ -121,7 +121,12 @@ enum SLAMaterial {
slamHeatResistant, slamHeatResistant,
}; };
enum DenseInfillAlgo { enum DenseInfillAlgo {
dfaAutomatic, dfaAutoNotFull, dfaAutoOrEnlarged , dfaEnlarged, dfaAutomatic,
dfaAutoNotFull,
dfaAutoOrEnlarged,
dfaAutoOrNothing,
dfaEnlarged,
dfaDisabled,
}; };
enum NoPerimeterUnsupportedAlgo { enum NoPerimeterUnsupportedAlgo {
@ -313,8 +318,9 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::ge
template<> inline const t_config_enum_values& ConfigOptionEnum<DenseInfillAlgo>::get_enum_values() { template<> inline const t_config_enum_values& ConfigOptionEnum<DenseInfillAlgo>::get_enum_values() {
static const t_config_enum_values keys_map = { static const t_config_enum_values keys_map = {
{ "automatic", dfaAutomatic }, { "automatic", dfaAutomatic },
{ "autosmall", dfaAutoNotFull }, { "autonotfull", dfaAutoNotFull },
{ "autoenlarged", dfaAutoOrEnlarged }, { "autoenlarged", dfaAutoOrEnlarged },
{ "autosmall", dfaAutoOrNothing},
{ "enlarged", dfaEnlarged } { "enlarged", dfaEnlarged }
}; };
return keys_map; return keys_map;

View File

@ -1193,7 +1193,7 @@ namespace Slic3r {
ExPolygons dense_polys; ExPolygons dense_polys;
std::vector<uint16_t> dense_priority; std::vector<uint16_t> dense_priority;
const ExPolygons surfs_with_overlap = { surface.expolygon }; 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 scaled_width = layerm->flow(frInfill, true).scaled_width();
coord_t overlap = scaled_width / 4; coord_t overlap = scaled_width / 4;
for (const ExPolygon& surf_with_overlap : surfs_with_overlap) { for (const ExPolygon& surf_with_overlap : surfs_with_overlap) {
@ -1203,46 +1203,89 @@ namespace Slic3r {
if (upp.has_fill_solid()) { if (upp.has_fill_solid()) {
// i'm using intersection_ex because the result different than // i'm using intersection_ex because the result different than
// upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon) // 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 = ExPolygons intersect =
offset2_ex( offset2_ex(
intersection_ex(sparse_polys, { upp.expolygon }, true) intersection_ex(sparse_polys, { upp.expolygon }, true)
, (float)-layerm->flow(frInfill).scaled_width(), (float)layerm->flow(frInfill).scaled_width()); , (float)-layerm->flow(frInfill).scaled_width(), (float)layerm->flow(frInfill).scaled_width());
if (!intersect.empty()) { if (!intersect.empty()) {
double area_intersect = 0; DenseInfillAlgo algo = layerm->region()->config().infill_dense_algo.value;
// 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();
double surf_with_overlap_area = surf_with_overlap.area(); //if no infill, don't bother, it's always yes
if (layerm->region()->config().infill_dense_algo.value == dfaEnlarged if (region->config().fill_density.value == 0) {
|| (layerm->region()->config().infill_dense_algo.value == dfaAutoOrEnlarged && surf_with_overlap_area <= area_intersect * COEFF_SPLIT)) { 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 //expand the area a bit
intersect = offset_ex(intersect, (scaled(layerm->region()->config().external_infill_margin.get_abs_value( 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)))))); 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 intersect = intersection_ex(intersect, sparse_polys);
|| layerm->region()->config().infill_dense_algo.value == dfaAutomatic) { } else if (dfaDisabled == algo) {
intersect.clear();
//like intersect.empty() but more resilient } else {
if (layerm->region()->config().infill_dense_algo.value == dfaAutomatic double sparse_area = surf_with_overlap.area();
|| surf_with_overlap_area > area_intersect * COEFF_SPLIT) { double area_to_cover = 0;
ExPolygons cover_intersect; double min_area_to_cover = 0;
if (dfaAutoNotFull == algo) {
// it will be a dense infill, split the surface if needed // calculate area to decide if area is small enough for autofill
//ExPolygons cover_intersect; for (ExPolygon poly_inter : intersect)
for (ExPolygon& expoly_tocover : intersect) { area_to_cover += poly_inter.area();
ExPolygons temp = dense_fill_fit_to_size( // if we have to fill everything, don't bother
expoly_tocover, if (area_to_cover * 1.1 > sparse_area)
surf_with_overlap, intersect.clear();
4 * layerm->flow(frInfill).scaled_width(),
0.01f);
cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end());
}
intersect = cover_intersect;
} else {
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()) { if (!intersect.empty()) {