Ensuring improvements and fixes:

Fix issue https://github.com/prusa3d/PrusaSlicer/issues/9978  -  too agressive filtering caused holes in top surfaces
Fix issue https://github.com/prusa3d/PrusaSlicer/issues/10231  - thin bridges not anchored, again due to too aggressive ensuring filter
Fix issue https://github.com/prusa3d/PrusaSlicer/issues/9988  -
	Slicing with 1 top/bottom surface and very low min shell thickness caused non-anchored solid fills.
	Fixed by handling as a special case.
This commit is contained in:
PavelMikus 2023-04-05 18:06:02 +02:00
parent e93b222d33
commit b5514120e5
2 changed files with 37 additions and 36 deletions

View File

@ -32,20 +32,20 @@ BeadingStrategyPtr BeadingStrategyFactory::makeStrategy(
) )
{ {
BeadingStrategyPtr ret = std::make_unique<DistributedBeadingStrategy>(preferred_bead_width_inner, preferred_transition_length, transitioning_angle, wall_split_middle_threshold, wall_add_middle_threshold, inward_distributed_center_wall_count); BeadingStrategyPtr ret = std::make_unique<DistributedBeadingStrategy>(preferred_bead_width_inner, preferred_transition_length, transitioning_angle, wall_split_middle_threshold, wall_add_middle_threshold, inward_distributed_center_wall_count);
BOOST_LOG_TRIVIAL(debug) << "Applying the Redistribute meta-strategy with outer-wall width = " << preferred_bead_width_outer << ", inner-wall width = " << preferred_bead_width_inner << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the Redistribute meta-strategy with outer-wall width = " << preferred_bead_width_outer << ", inner-wall width = " << preferred_bead_width_inner << ".";
ret = std::make_unique<RedistributeBeadingStrategy>(preferred_bead_width_outer, minimum_variable_line_ratio, std::move(ret)); ret = std::make_unique<RedistributeBeadingStrategy>(preferred_bead_width_outer, minimum_variable_line_ratio, std::move(ret));
if (print_thin_walls) { if (print_thin_walls) {
BOOST_LOG_TRIVIAL(debug) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the Widening Beading meta-strategy with minimum input width " << min_feature_size << " and minimum output width " << min_bead_width << ".";
ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width); ret = std::make_unique<WideningBeadingStrategy>(std::move(ret), min_feature_size, min_bead_width);
} }
if (outer_wall_offset > 0) { if (outer_wall_offset > 0) {
BOOST_LOG_TRIVIAL(debug) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the OuterWallOffset meta-strategy with offset = " << outer_wall_offset << ".";
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret)); ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
} }
//Apply the LimitedBeadingStrategy last, since that adds a 0-width marker wall which other beading strategies shouldn't touch. //Apply the LimitedBeadingStrategy last, since that adds a 0-width marker wall which other beading strategies shouldn't touch.
BOOST_LOG_TRIVIAL(debug) << "Applying the Limited Beading meta-strategy with maximum bead count = " << max_bead_count << "."; BOOST_LOG_TRIVIAL(trace) << "Applying the Limited Beading meta-strategy with maximum bead count = " << max_bead_count << ".";
ret = std::make_unique<LimitedBeadingStrategy>(max_bead_count, std::move(ret)); ret = std::make_unique<LimitedBeadingStrategy>(max_bead_count, std::move(ret));
return ret; return ret;
} }

View File

@ -1178,19 +1178,6 @@ void PrintObject::discover_vertical_shells()
}; };
bool spiral_vase = this->print()->config().spiral_vase.value; bool spiral_vase = this->print()->config().spiral_vase.value;
size_t num_layers = spiral_vase ? std::min(size_t(this->printing_region(0).config().bottom_solid_layers), m_layers.size()) : m_layers.size(); size_t num_layers = spiral_vase ? std::min(size_t(this->printing_region(0).config().bottom_solid_layers), m_layers.size()) : m_layers.size();
coordf_t min_layer_height = this->slicing_parameters().min_layer_height;
// Does this region possibly produce more than 1 top or bottom layer?
auto has_extra_layers_fn = [min_layer_height](const PrintRegionConfig &config) {
auto num_extra_layers = [min_layer_height](int num_solid_layers, coordf_t min_shell_thickness) {
if (num_solid_layers == 0)
return 0;
int n = num_solid_layers - 1;
int n2 = int(ceil(min_shell_thickness / min_layer_height));
return std::max(n, n2 - 1);
};
return num_extra_layers(config.top_solid_layers, config.top_solid_min_thickness) +
num_extra_layers(config.bottom_solid_layers, config.bottom_solid_min_thickness) > 0;
};
std::vector<DiscoverVerticalShellsCacheEntry> cache_top_botom_regions(num_layers, DiscoverVerticalShellsCacheEntry()); std::vector<DiscoverVerticalShellsCacheEntry> cache_top_botom_regions(num_layers, DiscoverVerticalShellsCacheEntry());
bool top_bottom_surfaces_all_regions = this->num_printing_regions() > 1 && ! m_config.interface_shells.value; bool top_bottom_surfaces_all_regions = this->num_printing_regions() > 1 && ! m_config.interface_shells.value;
// static constexpr const float top_bottom_expansion_coeff = 1.05f; // static constexpr const float top_bottom_expansion_coeff = 1.05f;
@ -1199,18 +1186,6 @@ void PrintObject::discover_vertical_shells()
if (top_bottom_surfaces_all_regions) { if (top_bottom_surfaces_all_regions) {
// This is a multi-material print and interface_shells are disabled, meaning that the vertical shell thickness // This is a multi-material print and interface_shells are disabled, meaning that the vertical shell thickness
// is calculated over all materials. // is calculated over all materials.
// Is the "ensure vertical wall thickness" applicable to any region?
bool has_extra_layers = false;
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) {
const PrintRegionConfig &config = this->printing_region(region_id).config();
if (has_extra_layers_fn(config)) {
has_extra_layers = true;
break;
}
}
if (! has_extra_layers)
// The "ensure vertical wall thickness" feature is not applicable to any of the regions. Quit.
return;
BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - start : cache top / bottom"; BOOST_LOG_TRIVIAL(debug) << "Discovering vertical shells in parallel - start : cache top / bottom";
//FIXME Improve the heuristics for a grain size. //FIXME Improve the heuristics for a grain size.
size_t grain_size = std::max(num_layers / 16, size_t(1)); size_t grain_size = std::max(num_layers / 16, size_t(1));
@ -1280,11 +1255,6 @@ void PrintObject::discover_vertical_shells()
} }
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) { for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
const PrintRegion &region = this->printing_region(region_id);
if (! has_extra_layers_fn(region.config()))
// Zero or 1 layer, there is no additional vertical wall thickness enforced.
continue;
//FIXME Improve the heuristics for a grain size. //FIXME Improve the heuristics for a grain size.
size_t grain_size = std::max(num_layers / 16, size_t(1)); size_t grain_size = std::max(num_layers / 16, size_t(1));
@ -1395,13 +1365,25 @@ void PrintObject::discover_vertical_shells()
coordf_t print_z = layer->print_z; coordf_t print_z = layer->print_z;
int i = int(idx_layer) + 1; int i = int(idx_layer) + 1;
int itop = int(idx_layer) + n_top_layers; int itop = int(idx_layer) + n_top_layers;
bool at_least_one_top_projected = false;
for (; i < int(cache_top_botom_regions.size()) && for (; i < int(cache_top_botom_regions.size()) &&
(i < itop || m_layers[i]->print_z - print_z < region_config.top_solid_min_thickness - EPSILON); (i < itop || m_layers[i]->print_z - print_z < region_config.top_solid_min_thickness - EPSILON);
++ i) { ++ i) {
at_least_one_top_projected = true;
const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i]; const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i];
combine_holes(cache.holes); combine_holes(cache.holes);
combine_shells(cache.top_surfaces); combine_shells(cache.top_surfaces);
} }
if (!at_least_one_top_projected && i < int(cache_top_botom_regions.size())) {
// Lets consider this a special case - with only 1 top solid and minimal shell thickness settings, the
// boundaries of solid layers are not anchored over/under perimeters, so lets fix it by adding at least one
// perimeter width of area
Polygons anchor_area = intersection(expand(cache_top_botom_regions[idx_layer].top_surfaces,
layerm->flow(frExternalPerimeter).scaled_spacing()),
to_polygons(m_layers[i]->lslices));
combine_shells(anchor_area);
}
if (one_more_layer_below_top_bottom_surfaces) if (one_more_layer_below_top_bottom_surfaces)
if (i < int(cache_top_botom_regions.size()) && if (i < int(cache_top_botom_regions.size()) &&
(i <= itop || m_layers[i]->bottom_z() - print_z < region_config.top_solid_min_thickness - EPSILON)) (i <= itop || m_layers[i]->bottom_z() - print_z < region_config.top_solid_min_thickness - EPSILON))
@ -1412,13 +1394,23 @@ void PrintObject::discover_vertical_shells()
coordf_t bottom_z = layer->bottom_z(); coordf_t bottom_z = layer->bottom_z();
int i = int(idx_layer) - 1; int i = int(idx_layer) - 1;
int ibottom = int(idx_layer) - n_bottom_layers; int ibottom = int(idx_layer) - n_bottom_layers;
bool at_least_one_bottom_projected = false;
for (; i >= 0 && for (; i >= 0 &&
(i > ibottom || bottom_z - m_layers[i]->bottom_z() < region_config.bottom_solid_min_thickness - EPSILON); (i > ibottom || bottom_z - m_layers[i]->bottom_z() < region_config.bottom_solid_min_thickness - EPSILON);
-- i) { -- i) {
at_least_one_bottom_projected = true;
const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i]; const DiscoverVerticalShellsCacheEntry &cache = cache_top_botom_regions[i];
combine_holes(cache.holes); combine_holes(cache.holes);
combine_shells(cache.bottom_surfaces); combine_shells(cache.bottom_surfaces);
} }
if (!at_least_one_bottom_projected && i >= 0) {
Polygons anchor_area = intersection(expand(cache_top_botom_regions[idx_layer].bottom_surfaces,
layerm->flow(frExternalPerimeter).scaled_spacing()),
to_polygons(m_layers[i]->lslices));
combine_shells(anchor_area);
}
if (one_more_layer_below_top_bottom_surfaces) if (one_more_layer_below_top_bottom_surfaces)
if (i >= 0 && if (i >= 0 &&
(i > ibottom || bottom_z - m_layers[i]->print_z < region_config.bottom_solid_min_thickness - EPSILON)) (i > ibottom || bottom_z - m_layers[i]->print_z < region_config.bottom_solid_min_thickness - EPSILON))
@ -1514,10 +1506,19 @@ void PrintObject::discover_vertical_shells()
// Finally expand the infill a bit to remove tiny gaps between solid infill and the other regions. // Finally expand the infill a bit to remove tiny gaps between solid infill and the other regions.
narrow_sparse_infill_region_radius - tiny_overlap_radius, ClipperLib::jtSquare); narrow_sparse_infill_region_radius - tiny_overlap_radius, ClipperLib::jtSquare);
Polygons internal_volume;
{
Polygons shrinked_bottom_slice = idx_layer > 0 ? to_polygons(m_layers[idx_layer - 1]->lslices) : Polygons{};
Polygons shrinked_upper_slice = idx_layer > 0 ? to_polygons(m_layers[idx_layer + 1]->lslices) : Polygons{};
internal_volume = intersection(shrinked_bottom_slice, shrinked_upper_slice);
}
// The opening operation may cause scattered tiny drops on the smooth parts of the model, filter them out // The opening operation may cause scattered tiny drops on the smooth parts of the model, filter them out
regularized_shell.erase(std::remove_if(regularized_shell.begin(), regularized_shell.end(), regularized_shell.erase(std::remove_if(regularized_shell.begin(), regularized_shell.end(),
[&min_perimeter_infill_spacing](const ExPolygon &p) { [&min_perimeter_infill_spacing, &internal_volume](const ExPolygon &p) {
return p.area() < min_perimeter_infill_spacing * scaled(8.0); return p.area() < min_perimeter_infill_spacing * scaled(1.5) ||
(p.area() < min_perimeter_infill_spacing * scaled(8.0) &&
diff(to_polygons(p), internal_volume).empty());
}), }),
regularized_shell.end()); regularized_shell.end());
} }