Ported PrintObject::slice() to C++

This commit is contained in:
Alessandro Ranellucci 2018-11-26 21:13:04 +01:00
parent 2bbb089a4f
commit f7509f2a3f
4 changed files with 80 additions and 94 deletions

View File

@ -34,95 +34,6 @@ sub support_layers {
return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ]; return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ];
} }
# 1) Decides Z positions of the layers,
# 2) Initializes layers and their regions
# 3) Slices the object meshes
# 4) Slices the modifier meshes and reclassifies the slices of the object meshes by the slices of the modifier meshes
# 5) Applies size compensation (offsets the slices in XY plane)
# 6) Replaces bad slices by the slices reconstructed from the upper/lower layer
# Resulting expolygons of layer regions are marked as Internal.
#
# this should be idempotent
sub slice {
my $self = shift;
return if $self->step_done(STEP_SLICE);
$self->set_step_started(STEP_SLICE);
$self->print->status_cb->(10, "Processing triangulated mesh");
$self->_slice;
# detect slicing errors
my $warning_thrown = 0;
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
if ($self->print->config->resolution) {
$self->_simplify_slices(scale($self->print->config->resolution));
}
die "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n"
if !@{$self->layers};
$self->set_typed_slices(0);
$self->set_step_done(STEP_SLICE);
}
sub make_perimeters { sub make_perimeters {
my ($self) = @_; my ($self) = @_;

View File

@ -41,6 +41,7 @@ class ExPolygonCollection
/// ExPolygons and check if at least one contains the point. /// ExPolygons and check if at least one contains the point.
bool contains(const Point &point) const; bool contains(const Point &point) const;
bool empty() const { return expolygons.empty(); }
size_t size() const { return expolygons.size(); } size_t size() const { return expolygons.size(); }
ExPolygons::iterator begin() { return expolygons.begin(); } ExPolygons::iterator begin() { return expolygons.begin(); }
ExPolygons::iterator end() { return expolygons.end(); } ExPolygons::iterator end() { return expolygons.end(); }

View File

@ -956,6 +956,17 @@ PrintObject::make_perimeters()
this->_make_perimeters(); this->_make_perimeters();
} }
/*
1) Decides Z positions of the layers,
2) Initializes layers and their regions
3) Slices the object meshes
4) Slices the modifier meshes and reclassifies the slices of the object meshes by the slices of the modifier meshes
5) Applies size compensation (offsets the slices in XY plane)
6) Replaces bad slices by the slices reconstructed from the upper/lower layer
Resulting expolygons of layer regions are marked as Internal.
This should be idempotent.
*/
void void
PrintObject::slice() PrintObject::slice()
{ {
@ -964,8 +975,7 @@ PrintObject::slice()
if (_print->status_cb != nullptr) { if (_print->status_cb != nullptr) {
_print->status_cb(10, "Processing triangulated mesh"); _print->status_cb(10, "Processing triangulated mesh");
} }
this->_slice(); this->_slice();
// detect slicing errors // detect slicing errors
@ -975,12 +985,75 @@ PrintObject::slice()
<< "I tried to repair it, however you might want to check " << "I tried to repair it, however you might want to check "
<< "the results or repair the input file and retry.\n"; << "the results or repair the input file and retry.\n";
if (this->layers.size() == 0) { bool warning_thrown = false;
for (size_t i = 0; i < this->layer_count(); ++i) {
Layer* layer{ this->get_layer(i) };
if (!layer->slicing_errors) continue;
if (!warning_thrown) {
Slic3r::Log::warn("PrintObject") << "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 = true;
}
// try to repair the layer surfaces by merging all contours and all holes from
// neighbor layers
#ifdef SLIC3R_DEBUG
std::cout << "Attempting to repair layer " << i << std::endl;
#endif
for (size_t region_id = 0; region_id < layer->region_count(); ++region_id) {
LayerRegion* layerm{ layer->get_region(region_id) };
ExPolygons slices;
for (size_t j = i+1; j < this->layer_count(); ++j) {
const Layer* upper = this->get_layer(j);
if (!upper->slicing_errors) {
append_to(slices, (ExPolygons)upper->get_region(region_id)->slices);
break;
}
}
for (int j = i-1; j >= 0; --j) {
const Layer* lower = this->get_layer(j);
if (!lower->slicing_errors) {
append_to(slices, (ExPolygons)lower->get_region(region_id)->slices);
break;
}
}
// TODO: do we actually need to split contours and holes before performing the diff?
Polygons contours, holes;
for (ExPolygon ex : slices)
contours.push_back(ex.contour);
for (ExPolygon ex : slices)
append_to(holes, ex.holes);
const ExPolygons diff = diff_ex(contours, holes);
layerm->slices.clear();
layerm->slices.append(diff, stInternal);
}
// update layer slices after repairing the single regions
layer->make_slices();
}
// remove empty layers from bottom
while (!this->layers.empty() && this->get_layer(0)->slices.empty()) {
this->delete_layer(0);
for (Layer* layer : this->layers)
layer->set_id(layer->id()-1);
}
// simplify slices if required
if (this->_print->config.resolution() > 0)
this->_simplify_slices(scale_(this->_print->config.resolution()));
if (this->layers.empty()) {
Slic3r::Log::error("PrintObject") << "slice(): " << "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n"; Slic3r::Log::error("PrintObject") << "slice(): " << "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n";
return; // make this throw an exception instead? return; // make this throw an exception instead?
} }
this->typed_slices = false; this->typed_slices = false;
this->state.set_done(posSlice); this->state.set_done(posSlice);
} }

View File

@ -132,6 +132,7 @@ _constant()
void combine_infill(); void combine_infill();
void discover_horizontal_shells(); void discover_horizontal_shells();
void clip_fill_surfaces(); void clip_fill_surfaces();
void slice();
void _slice(); void _slice();
SV* _slice_region(size_t region_id, std::vector<double> z, bool modifier) SV* _slice_region(size_t region_id, std::vector<double> z, bool modifier)
%code%{ %code%{