Fixing of slicing errors ported to C++, parallelized.
This commit is contained in:
parent
73439b7acb
commit
4331f38912
@ -46,66 +46,10 @@ sub slice {
|
|||||||
$self->print->status_cb->(10, "Processing triangulated mesh");
|
$self->print->status_cb->(10, "Processing triangulated mesh");
|
||||||
|
|
||||||
$self->_slice;
|
$self->_slice;
|
||||||
|
|
||||||
# detect slicing errors
|
my $warning = $self->_fix_slicing_errors;
|
||||||
my $warning_thrown = 0;
|
warn $warning if (defined($warning) && $warning ne '');
|
||||||
for my $i (0 .. ($self->layer_count - 1)) {
|
|
||||||
my $layer = $self->get_layer($i);
|
|
||||||
next unless $layer->slicing_errors;
|
|
||||||
if (!$warning_thrown) {
|
|
||||||
warn "The model has overlapping or self-intersecting facets. I tried to repair it, "
|
|
||||||
. "however you might want to check the results or repair the input file and retry.\n";
|
|
||||||
$warning_thrown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# try to repair the layer surfaces by merging all contours and all holes from
|
|
||||||
# neighbor layers
|
|
||||||
Slic3r::debugf "Attempting to repair layer %d\n", $i;
|
|
||||||
|
|
||||||
foreach my $region_id (0 .. ($layer->region_count - 1)) {
|
|
||||||
my $layerm = $layer->region($region_id);
|
|
||||||
|
|
||||||
my (@upper_surfaces, @lower_surfaces);
|
|
||||||
for (my $j = $i+1; $j < $self->layer_count; $j++) {
|
|
||||||
if (!$self->get_layer($j)->slicing_errors) {
|
|
||||||
@upper_surfaces = @{$self->get_layer($j)->region($region_id)->slices};
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (my $j = $i-1; $j >= 0; $j--) {
|
|
||||||
if (!$self->get_layer($j)->slicing_errors) {
|
|
||||||
@lower_surfaces = @{$self->get_layer($j)->region($region_id)->slices};
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $union = union_ex([
|
|
||||||
map $_->expolygon->contour, @upper_surfaces, @lower_surfaces,
|
|
||||||
]);
|
|
||||||
my $diff = diff_ex(
|
|
||||||
[ map @$_, @$union ],
|
|
||||||
[ map @{$_->expolygon->holes}, @upper_surfaces, @lower_surfaces, ],
|
|
||||||
);
|
|
||||||
|
|
||||||
$layerm->slices->clear;
|
|
||||||
$layerm->slices->append($_)
|
|
||||||
for map Slic3r::Surface->new
|
|
||||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL),
|
|
||||||
@$diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
# update layer slices after repairing the single regions
|
|
||||||
$layer->make_slices;
|
|
||||||
}
|
|
||||||
|
|
||||||
# remove empty layers from bottom
|
|
||||||
while (@{$self->layers} && !@{$self->get_layer(0)->slices}) {
|
|
||||||
$self->delete_layer(0);
|
|
||||||
for (my $i = 0; $i <= $#{$self->layers}; $i++) {
|
|
||||||
$self->get_layer($i)->set_id( $self->get_layer($i)->id-1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# simplify slices if required
|
# simplify slices if required
|
||||||
if ($self->print->config->resolution) {
|
if ($self->print->config->resolution) {
|
||||||
$self->_simplify_slices(scale($self->print->config->resolution));
|
$self->_simplify_slices(scale($self->print->config->resolution));
|
||||||
|
@ -168,6 +168,7 @@ public:
|
|||||||
SlicingParameters slicing_parameters() const;
|
SlicingParameters slicing_parameters() const;
|
||||||
|
|
||||||
void _slice();
|
void _slice();
|
||||||
|
std::string _fix_slicing_errors();
|
||||||
bool has_support_material() const;
|
bool has_support_material() const;
|
||||||
void detect_surfaces_type();
|
void detect_surfaces_type();
|
||||||
void process_external_surfaces();
|
void process_external_surfaces();
|
||||||
|
@ -1133,6 +1133,7 @@ void PrintObject::_slice()
|
|||||||
end:
|
end:
|
||||||
;
|
;
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, this->layers.size()),
|
tbb::blocked_range<size_t>(0, this->layers.size()),
|
||||||
[this](const tbb::blocked_range<size_t>& range) {
|
[this](const tbb::blocked_range<size_t>& range) {
|
||||||
@ -1170,6 +1171,7 @@ end:
|
|||||||
layer->make_slices();
|
layer->make_slices();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::vector<float> &z, bool modifier)
|
std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::vector<float> &z, bool modifier)
|
||||||
@ -1203,6 +1205,85 @@ std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::
|
|||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string PrintObject::_fix_slicing_errors()
|
||||||
|
{
|
||||||
|
// Collect layers with slicing errors.
|
||||||
|
// These layers will be fixed in parallel.
|
||||||
|
std::vector<size_t> buggy_layers;
|
||||||
|
buggy_layers.reserve(this->layers.size());
|
||||||
|
for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer)
|
||||||
|
if (this->layers[idx_layer]->slicing_errors)
|
||||||
|
buggy_layers.push_back(idx_layer);
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - begin";
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, buggy_layers.size()),
|
||||||
|
[this, &buggy_layers](const tbb::blocked_range<size_t>& range) {
|
||||||
|
for (size_t buggy_layer_idx = range.begin(); buggy_layer_idx < range.end(); ++ buggy_layer_idx) {
|
||||||
|
size_t idx_layer = buggy_layers[buggy_layer_idx];
|
||||||
|
Layer *layer = this->layers[idx_layer];
|
||||||
|
assert(layer->slicing_errors);
|
||||||
|
// Try to repair the layer surfaces by merging all contours and all holes from neighbor layers.
|
||||||
|
// BOOST_LOG_TRIVIAL(trace) << "Attempting to repair layer" << idx_layer;
|
||||||
|
for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id) {
|
||||||
|
LayerRegion *layerm = layer->regions[region_id];
|
||||||
|
// Find the first valid layer below / above the current layer.
|
||||||
|
const Surfaces *upper_surfaces = nullptr;
|
||||||
|
const Surfaces *lower_surfaces = nullptr;
|
||||||
|
for (size_t j = idx_layer + 1; j < this->layers.size(); ++ j)
|
||||||
|
if (! this->layers[j]->slicing_errors) {
|
||||||
|
upper_surfaces = &this->layers[j]->regions[region_id]->slices.surfaces;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int j = int(idx_layer) - 1; j >= 0; -- j)
|
||||||
|
if (! this->layers[j]->slicing_errors) {
|
||||||
|
lower_surfaces = &this->layers[j]->regions[region_id]->slices.surfaces;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Collect outer contours and holes from the valid layers above & below.
|
||||||
|
Polygons outer;
|
||||||
|
outer.reserve(
|
||||||
|
((upper_surfaces == nullptr) ? 0 : upper_surfaces->size()) +
|
||||||
|
((lower_surfaces == nullptr) ? 0 : lower_surfaces->size()));
|
||||||
|
size_t num_holes = 0;
|
||||||
|
if (upper_surfaces)
|
||||||
|
for (const auto &surface : *upper_surfaces) {
|
||||||
|
outer.push_back(surface.expolygon.contour);
|
||||||
|
num_holes += surface.expolygon.holes.size();
|
||||||
|
}
|
||||||
|
if (lower_surfaces)
|
||||||
|
for (const auto &surface : *lower_surfaces) {
|
||||||
|
outer.push_back(surface.expolygon.contour);
|
||||||
|
num_holes += surface.expolygon.holes.size();
|
||||||
|
}
|
||||||
|
Polygons holes;
|
||||||
|
holes.reserve(num_holes);
|
||||||
|
if (upper_surfaces)
|
||||||
|
for (const auto &surface : *upper_surfaces)
|
||||||
|
polygons_append(holes, surface.expolygon.holes);
|
||||||
|
if (lower_surfaces)
|
||||||
|
for (const auto &surface : *lower_surfaces)
|
||||||
|
polygons_append(holes, surface.expolygon.holes);
|
||||||
|
layerm->slices.set(diff_ex(union_(outer), holes, false), stInternal);
|
||||||
|
}
|
||||||
|
// Update layer slices after repairing the single regions.
|
||||||
|
layer->make_slices();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - end";
|
||||||
|
|
||||||
|
// remove empty layers from bottom
|
||||||
|
while (! this->layers.empty() && this->layers.front()->slices.expolygons.empty()) {
|
||||||
|
this->delete_layer(0);
|
||||||
|
for (size_t i = 0; i < this->layers.size(); ++ i)
|
||||||
|
this->layers[i]->set_id(this->layers[i]->id() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buggy_layers.empty() ? "" :
|
||||||
|
"The model has overlapping or self-intersecting facets. I tried to repair it, "
|
||||||
|
"however you might want to check the results or repair the input file and retry.\n";
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PrintObject::_make_perimeters()
|
PrintObject::_make_perimeters()
|
||||||
{
|
{
|
||||||
|
@ -112,6 +112,7 @@ _constant()
|
|||||||
%code%{ THIS->state.set_started(step); %};
|
%code%{ THIS->state.set_started(step); %};
|
||||||
|
|
||||||
void _slice();
|
void _slice();
|
||||||
|
std::string _fix_slicing_errors();
|
||||||
void detect_surfaces_type();
|
void detect_surfaces_type();
|
||||||
void process_external_surfaces();
|
void process_external_surfaces();
|
||||||
void discover_vertical_shells();
|
void discover_vertical_shells();
|
||||||
|
Loading…
Reference in New Issue
Block a user