Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2021-12-08 11:45:48 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-12-08 11:45:59 +0300
commitc9727b5a57d0e78c386130c1eee5bb330d3b7cee (patch)
tree210d4f52b7064a53d34302a2c27d6e99348d12ab
parent175a6369fdf38187ca16c03e9af01985b9623f71 (diff)
Fix of Random placment of top fill throughout model #7442
For this particular model, ClipperLib numerical instability causes one of the internal surfaces to turn into bridging surfaces on reslicing. The issue was fixed by reverting to untyped slices if possible.
-rw-r--r--src/libslic3r/Layer.cpp21
-rw-r--r--src/libslic3r/Layer.hpp2
-rw-r--r--src/libslic3r/LayerRegion.cpp3
-rw-r--r--src/libslic3r/PrintObject.cpp11
4 files changed, 34 insertions, 3 deletions
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<unsigned short, Surfaces> 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 <class T> 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<SurfacesPtr> by_surface;
- by_surface.assign(size_t(stCount), SurfacesPtr());
+ std::array<SurfacesPtr, size_t(stCount)> 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