Fix of re-slicing with multiple regions.
This is a fix of a bug, which was in Slic3r forever, where raw slices were not cached, but recalculated from classified regions, where merging the regions did not produce the original contour reliably. Fixes [2.3.0-beta2] Odd bad slicing related to infill (?) percentage #5407
This commit is contained in:
parent
cc7dbf8925
commit
a2959ec944
@ -64,19 +64,30 @@ void Layer::make_slices()
|
|||||||
this->lslices.emplace_back(std::move(slices[i]));
|
this->lslices.emplace_back(std::move(slices[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
static inline bool layer_needs_raw_backup(const Layer *layer)
|
||||||
void Layer::merge_slices()
|
|
||||||
{
|
{
|
||||||
if (m_regions.size() == 1 && (this->id() > 0 || this->object()->config().elefant_foot_compensation.value == 0)) {
|
return ! (layer->regions().size() == 1 && (layer->id() > 0 || layer->object()->config().elefant_foot_compensation.value == 0));
|
||||||
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
}
|
||||||
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
|
||||||
// Don't use this optimization on 1st layer with Elephant foot compensation applied, as this->lslices are uncompensated,
|
void Layer::backup_untyped_slices()
|
||||||
// while regions are compensated.
|
{
|
||||||
m_regions.front()->slices.set(this->lslices, stInternal);
|
if (layer_needs_raw_backup(this)) {
|
||||||
} else {
|
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions)
|
||||||
// without safety offset, artifacts are generated (upstream Slic3r GH #2494)
|
layerm->raw_slices = to_expolygons(layerm->slices.surfaces);
|
||||||
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stInternal);
|
} else {
|
||||||
|
assert(m_regions.size() == 1);
|
||||||
|
m_regions.front()->raw_slices.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::restore_untyped_slices()
|
||||||
|
{
|
||||||
|
if (layer_needs_raw_backup(this)) {
|
||||||
|
for (LayerRegion *layerm : m_regions)
|
||||||
|
layerm->slices.set(layerm->raw_slices, stInternal);
|
||||||
|
} else {
|
||||||
|
assert(m_regions.size() == 1);
|
||||||
|
m_regions.front()->slices.set(this->lslices, stInternal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@ public:
|
|||||||
// collection of surfaces generated by slicing the original geometry
|
// collection of surfaces generated by slicing the original geometry
|
||||||
// divided by type top/bottom/internal
|
// divided by type top/bottom/internal
|
||||||
SurfaceCollection slices;
|
SurfaceCollection slices;
|
||||||
|
// Backed up slices before they are split into top/bottom/internal.
|
||||||
|
// Only backed up for multi-region layers or layers with elephant foot compensation.
|
||||||
|
//FIXME Review whether not to simplify the code by keeping the raw_slices all the time.
|
||||||
|
ExPolygons raw_slices;
|
||||||
|
|
||||||
// collection of extrusion paths/loops filling gaps
|
// collection of extrusion paths/loops filling gaps
|
||||||
// These fills are generated by the perimeter generator.
|
// These fills are generated by the perimeter generator.
|
||||||
@ -125,8 +129,10 @@ public:
|
|||||||
// Test whether whether there are any slices assigned to this layer.
|
// Test whether whether there are any slices assigned to this layer.
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
void make_slices();
|
void make_slices();
|
||||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
// Backup and restore raw sliced regions if needed.
|
||||||
void merge_slices();
|
//FIXME Review whether not to simplify the code by keeping the raw_slices all the time.
|
||||||
|
void backup_untyped_slices();
|
||||||
|
void restore_untyped_slices();
|
||||||
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
|
// 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;
|
ExPolygons merged(float offset) const;
|
||||||
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
||||||
|
@ -186,7 +186,7 @@ public:
|
|||||||
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
||||||
std::vector<unsigned int> object_extruders() const;
|
std::vector<unsigned int> object_extruders() const;
|
||||||
|
|
||||||
// Called when slicing to SVG (see Print.pm sub export_svg), and used by perimeters.t
|
// Called by make_perimeters()
|
||||||
void slice();
|
void slice();
|
||||||
|
|
||||||
// Helpers to slice support enforcer / blocker meshes by the support generator.
|
// Helpers to slice support enforcer / blocker meshes by the support generator.
|
||||||
|
@ -97,6 +97,7 @@ PrintBase::ApplyStatus PrintObject::set_instances(PrintInstances &&instances)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by make_perimeters()
|
||||||
// 1) Decides Z positions of the layers,
|
// 1) Decides Z positions of the layers,
|
||||||
// 2) Initializes layers and their regions
|
// 2) Initializes layers and their regions
|
||||||
// 3) Slices the object meshes
|
// 3) Slices the object meshes
|
||||||
@ -104,8 +105,6 @@ PrintBase::ApplyStatus PrintObject::set_instances(PrintInstances &&instances)
|
|||||||
// 5) Applies size compensation (offsets the slices in XY plane)
|
// 5) Applies size compensation (offsets the slices in XY plane)
|
||||||
// 6) Replaces bad slices by the slices reconstructed from the upper/lower layer
|
// 6) Replaces bad slices by the slices reconstructed from the upper/lower layer
|
||||||
// Resulting expolygons of layer regions are marked as Internal.
|
// Resulting expolygons of layer regions are marked as Internal.
|
||||||
//
|
|
||||||
// this should be idempotent
|
|
||||||
void PrintObject::slice()
|
void PrintObject::slice()
|
||||||
{
|
{
|
||||||
if (! this->set_started(posSlice))
|
if (! this->set_started(posSlice))
|
||||||
@ -125,7 +124,7 @@ void PrintObject::slice()
|
|||||||
// Simplify slices if required.
|
// Simplify slices if required.
|
||||||
if (m_print->config().resolution)
|
if (m_print->config().resolution)
|
||||||
this->simplify_slices(scale_(this->print()->config().resolution));
|
this->simplify_slices(scale_(this->print()->config().resolution));
|
||||||
// Update bounding boxes
|
// Update bounding boxes, back up raw slices of complex models.
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
[this](const tbb::blocked_range<size_t>& range) {
|
[this](const tbb::blocked_range<size_t>& range) {
|
||||||
@ -136,6 +135,7 @@ void PrintObject::slice()
|
|||||||
layer.lslices_bboxes.reserve(layer.lslices.size());
|
layer.lslices_bboxes.reserve(layer.lslices.size());
|
||||||
for (const ExPolygon &expoly : layer.lslices)
|
for (const ExPolygon &expoly : layer.lslices)
|
||||||
layer.lslices_bboxes.emplace_back(get_extents(expoly));
|
layer.lslices_bboxes.emplace_back(get_extents(expoly));
|
||||||
|
layer.backup_untyped_slices();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (m_layers.empty())
|
if (m_layers.empty())
|
||||||
@ -157,10 +157,10 @@ void PrintObject::make_perimeters()
|
|||||||
m_print->set_status(20, L("Generating perimeters"));
|
m_print->set_status(20, L("Generating perimeters"));
|
||||||
BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info();
|
BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info();
|
||||||
|
|
||||||
// merge slices if they were split into types
|
// Revert the typed slices into untyped slices.
|
||||||
if (m_typed_slices) {
|
if (m_typed_slices) {
|
||||||
for (Layer *layer : m_layers) {
|
for (Layer *layer : m_layers) {
|
||||||
layer->merge_slices();
|
layer->restore_untyped_slices();
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
}
|
}
|
||||||
m_typed_slices = false;
|
m_typed_slices = false;
|
||||||
|
@ -70,7 +70,8 @@
|
|||||||
%code%{ RETVAL = dynamic_cast<SupportLayer*>(THIS); %};
|
%code%{ RETVAL = dynamic_cast<SupportLayer*>(THIS); %};
|
||||||
|
|
||||||
void make_slices();
|
void make_slices();
|
||||||
void merge_slices();
|
void backup_untyped_slices();
|
||||||
|
void restore_untyped_slices();
|
||||||
void make_perimeters();
|
void make_perimeters();
|
||||||
void make_fills();
|
void make_fills();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user