diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 5c661ed68..f99cc674d 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -92,6 +92,25 @@ void Layer::restore_untyped_slices() } } +// Similar to Layer::restore_untyped_slices() +// To improve robustness of detect_surfaces_type() when reslicing (working with typed slices), see GH issue #7442. +// Only resetting layerm->slices if Slice::extra_perimeters is always zero or it will not be used anymore +// after the perimeter generator. +void Layer::restore_untyped_slices_no_extra_perimeters() +{ + if (layer_needs_raw_backup(this)) { + for (LayerRegion *layerm : m_regions) + if (layerm->region().config().extra_perimeters.value <= 0) + layerm->slices.set(layerm->raw_slices, stInternal); + } else { + assert(m_regions.size() == 1); + LayerRegion *layerm = m_regions.front(); + // This optimization is correct, as extra_perimeters are only reused by prepare_infill() with multi-regions. + //if (layerm->region().config().extra_perimeters.value <= 0) + layerm->slices.set(this->lslices, stInternal); + } +} + ExPolygons Layer::merged(float offset_scaled) const { assert(offset_scaled >= 0.f); @@ -179,7 +198,7 @@ void Layer::make_perimeters() // group slices (surfaces) according to number of extra perimeters std::map slices; // extra_perimeters => [ surface, surface... ] for (LayerRegion *layerm : layerms) { - for (Surface &surface : layerm->slices.surfaces) + for (const Surface &surface : layerm->slices.surfaces) slices[surface.extra_perimeters].emplace_back(surface); if (layerm->region().config().fill_density > layerm_config->region().config().fill_density) layerm_config = layerm; diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 516b6da9b..0071c7f6e 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -137,6 +137,8 @@ public: //FIXME Review whether not to simplify the code by keeping the raw_slices all the time. void backup_untyped_slices(); void restore_untyped_slices(); + // To improve robustness of detect_surfaces_type() when reslicing (working with typed slices), see GH issue #7442. + void restore_untyped_slices_no_extra_perimeters(); // Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices. ExPolygons merged(float offset) const; template bool any_internal_region_slice_contains(const T &item) const { diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index 4dbffe7b0..fd29d6d54 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -51,8 +51,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped() // so we're safe. This guarantees idempotence of prepare_infill() also in case // that combine_infill() turns some fill_surface into VOID surfaces. // Collect polygons per surface type. - std::vector by_surface; - by_surface.assign(size_t(stCount), SurfacesPtr()); + std::array by_surface; for (Surface &surface : this->slices.surfaces) by_surface[size_t(surface.surface_type)].emplace_back(&surface); // Trim surfaces by the fill_boundaries. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 97d13af75..05b8c9eb6 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -227,6 +227,17 @@ void PrintObject::prepare_infill() m_print->set_status(30, L("Preparing infill")); + if (m_typed_slices) { + // To improve robustness of detect_surfaces_type() when reslicing (working with typed slices), see GH issue #7442. + // The preceding step (perimeter generator) only modifies extra_perimeters and the extra perimeters are only used by discover_vertical_shells() + // with more than a single region. If this step does not use Surface::extra_perimeters or Surface::extra_perimeters is always zero, it is safe + // to reset to the untyped slices before re-runnning detect_surfaces_type(). + for (Layer* layer : m_layers) { + layer->restore_untyped_slices_no_extra_perimeters(); + m_print->throw_if_canceled(); + } + } + // This will assign a type (top/bottom/internal) to $layerm->slices. // Then the classifcation of $layerm->slices is transfered onto // the $layerm->fill_surfaces by clipping $layerm->fill_surfaces