From b1372d43659757b1a60d14dc5ba4819dc4124755 Mon Sep 17 00:00:00 2001 From: Florens Wasserfall Date: Thu, 23 Mar 2017 14:53:28 +0100 Subject: [PATCH] Ported most of slice() to C++ --- lib/Slic3r/Print/Object.pm | 263 +------------------------ xs/src/libslic3r/Print.hpp | 3 + xs/src/libslic3r/PrintObject.cpp | 240 ++++++++++++++++++++++ xs/src/libslic3r/Surface.hpp | 87 ++++++++ xs/src/libslic3r/SurfaceCollection.hpp | 10 + xs/xsp/Print.xsp | 1 + 6 files changed, 342 insertions(+), 262 deletions(-) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index d8e41d77e..937eb2e92 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -33,17 +33,6 @@ sub support_layers { return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ]; } -sub _adjust_layer_height { - my ($self, $lh) = @_; - - if ($self->print->config->z_steps_per_mm > 0) { - my $min_dz = 1/$self->print->config->z_steps_per_mm * 4; - $lh = int($lh / $min_dz + 0.5) * $min_dz; - } - - return $lh; -} - # 1) Decides Z positions of the layers, # 2) Initializes layers and their regions # 3) Slices the object meshes @@ -60,257 +49,7 @@ sub slice { $self->set_step_started(STEP_SLICE); $self->print->status_cb->(10, "Processing triangulated mesh"); - my $min_nozzle_diameter; - { - my @nozzle_diameters = map $self->print->config->get_at('nozzle_diameter', $_), - @{$self->print->object_extruders}; - - $min_nozzle_diameter = min(@nozzle_diameters); - my $lh = min($min_nozzle_diameter, $self->config->layer_height); - - $self->config->set('layer_height', $self->_adjust_layer_height($lh)); - } - - # init layers - { - $self->clear_layers; - - # make layers taking custom heights into account - my $id = 0; - my $print_z = 0; - my $first_object_layer_height = -1; - my $first_object_layer_distance = -1; - - # add raft layers - if ($self->config->raft_layers > 0) { - $id += $self->config->raft_layers; - - # raise first object layer Z by the thickness of the raft itself - # plus the extra distance required by the support material logic - my $first_layer_height = $self->config->get_value('first_layer_height'); - $print_z += $first_layer_height; - - # use a large height - my $support_material_layer_height; - { - my @nozzle_diameters = ( - map $self->print->config->get_at('nozzle_diameter', $_), - @{$self->support_material_extruders}, - ); - $support_material_layer_height = 0.75 * min(@nozzle_diameters); - } - $print_z += $support_material_layer_height * ($self->config->raft_layers - 1); - - # compute the average of all nozzles used for printing the object - my $nozzle_diameter; - { - my @nozzle_diameters = ( - map $self->print->config->get_at('nozzle_diameter', $_), @{$self->print->object_extruders} - ); - $nozzle_diameter = sum(@nozzle_diameters)/@nozzle_diameters; - } - $first_object_layer_distance = $self->_support_material->contact_distance($self->config->layer_height, $nozzle_diameter); - - # force first layer print_z according to the contact distance - # (the loop below will raise print_z by such height) - $first_object_layer_height = $first_object_layer_distance - $self->config->support_material_contact_distance; - } - - # loop until we have at least one layer and the max slice_z reaches the object height - my $slice_z = 0; - my $height = 0; - my $max_z = unscale($self->size->z); - while (($slice_z - $height) <= $max_z) { - # assign the default height to the layer according to the general settings - $height = ($id == 0) - ? $self->config->get_value('first_layer_height') - : $self->config->layer_height; - - # look for an applicable custom range - if (my $range = first { $_->[0] <= $slice_z && $_->[1] > $slice_z } @{$self->layer_height_ranges}) { - $height = $self->_adjust_layer_height($range->[2]); - - # if user set custom height to zero we should just skip the range and resume slicing over it - if ($height == 0) { - $slice_z += $range->[1] - $range->[0]; - next; - } - } - - if ($first_object_layer_height != -1 && !@{$self->layers}) { - $height = $first_object_layer_height; - $print_z += ($first_object_layer_distance - $height); - } - - $print_z += $height; - $slice_z += $height/2; - last if $slice_z > $max_z; - - ### Slic3r::debugf "Layer %d: height = %s; slice_z = %s; print_z = %s\n", $id, $height, $slice_z, $print_z; - - $self->add_layer($id, $height, $print_z, $slice_z); - if ($self->layer_count >= 2) { - my $lc = $self->layer_count; - $self->get_layer($lc - 2)->set_upper_layer($self->get_layer($lc - 1)); - $self->get_layer($lc - 1)->set_lower_layer($self->get_layer($lc - 2)); - } - $id++; - - $slice_z += $height/2; # add the other half layer - } - } - - # Reduce or thicken the top layer in order to match the original object size. - # This is not actually related to z_steps_per_mm but we only enable it in case - # user provided that value, as it means they really care about the layer height - # accuracy and we don't provide unexpected result for people noticing the last - # layer has a different layer height. - if ($self->print->config->z_steps_per_mm > 0) { - my $first_object_layer = $self->get_layer(0); - my $last_object_layer = $self->get_layer($self->layer_count-1); - my $print_height = $last_object_layer->print_z - $first_object_layer->print_z + $first_object_layer->height; - my $diff = $print_height - unscale($self->size->z); - if ($diff < 0) { - # we need to thicken last layer - $diff = min(abs($diff), $min_nozzle_diameter - $last_object_layer->height); - $last_object_layer->set_height($last_object_layer->height + $diff); - $last_object_layer->set_print_z($last_object_layer->print_z + $diff); - } else { - # we need to reduce last layer - # prevent generation of a too small layer - my $new_height = $last_object_layer->height - $diff; - if ($new_height < $min_nozzle_diameter/2) { - $last_object_layer->set_height($new_height); - $last_object_layer->set_print_z($last_object_layer->print_z - $diff); - } - } - } - - # make sure all layers contain layer region objects for all regions - my $regions_count = $self->print->region_count; - foreach my $layer (@{ $self->layers }) { - $layer->region($_) for 0 .. ($regions_count-1); - } - - # get array of Z coordinates for slicing - my @z = map $_->slice_z, @{$self->layers}; - - # slice all non-modifier volumes - for my $region_id (0..($self->region_count - 1)) { - my $expolygons_by_layer = $self->_slice_region($region_id, \@z, 0); - for my $layer_id (0..$#$expolygons_by_layer) { - my $layerm = $self->get_layer($layer_id)->regions->[$region_id]; - $layerm->slices->clear; - foreach my $expolygon (@{ $expolygons_by_layer->[$layer_id] }) { - $layerm->slices->append(Slic3r::Surface->new( - expolygon => $expolygon, - surface_type => S_TYPE_INTERNAL, - )); - } - } - } - - # then slice all modifier volumes - if ($self->region_count > 1) { - for my $region_id (0..$self->region_count) { - my $expolygons_by_layer = $self->_slice_region($region_id, \@z, 1); - - # loop through the other regions and 'steal' the slices belonging to this one - for my $other_region_id (0..$self->region_count) { - next if $other_region_id == $region_id; - - for my $layer_id (0..$#$expolygons_by_layer) { - my $layerm = $self->get_layer($layer_id)->regions->[$region_id]; - my $other_layerm = $self->get_layer($layer_id)->regions->[$other_region_id]; - next if !defined $other_layerm; - - my $other_slices = [ map $_->p, @{$other_layerm->slices} ]; # Polygons - my $my_parts = intersection_ex( - $other_slices, - [ map @$_, @{ $expolygons_by_layer->[$layer_id] } ], - ); - next if !@$my_parts; - - # append new parts to our region - foreach my $expolygon (@$my_parts) { - $layerm->slices->append(Slic3r::Surface->new( - expolygon => $expolygon, - surface_type => S_TYPE_INTERNAL, - )); - } - - # remove such parts from original region - $other_layerm->slices->clear; - $other_layerm->slices->append(Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNAL, - )) for @{ diff_ex($other_slices, [ map @$_, @$my_parts ]) }; - } - } - } - } - - # remove last layer(s) if empty - $self->delete_layer($self->layer_count - 1) - while $self->layer_count && (!map @{$_->slices}, @{$self->get_layer($self->layer_count - 1)->regions}); - - foreach my $layer (@{ $self->layers }) { - # apply size compensation - if ($self->config->xy_size_compensation != 0) { - my $delta = scale($self->config->xy_size_compensation); - if (@{$layer->regions} == 1) { - # single region - my $layerm = $layer->regions->[0]; - my $slices = [ map $_->p, @{$layerm->slices} ]; - $layerm->slices->clear; - $layerm->slices->append(Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNAL, - )) for @{offset_ex($slices, $delta)}; - } else { - if ($delta < 0) { - # multiple regions, shrinking - # we apply the offset to the combined shape, then intersect it - # with the original slices for each region - my $slices = union([ map $_->p, map @{$_->slices}, @{$layer->regions} ]); - $slices = offset($slices, $delta); - foreach my $layerm (@{$layer->regions}) { - my $this_slices = intersection_ex( - $slices, - [ map $_->p, @{$layerm->slices} ], - ); - $layerm->slices->clear; - $layerm->slices->append(Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNAL, - )) for @$this_slices; - } - } else { - # multiple regions, growing - # this is an ambiguous case, since it's not clear how to grow regions where they are going to overlap - # so we give priority to the first one and so on - for my $i (0..$#{$layer->regions}) { - my $layerm = $layer->regions->[$i]; - my $slices = offset_ex([ map $_->p, @{$layerm->slices} ], $delta); - if ($i > 0) { - $slices = diff_ex( - [ map @$_, @$slices ], - [ map $_->p, map @{$_->slices}, map $layer->regions->[$_], 0..($i-1) ], # slices of already processed regions - ); - } - $layerm->slices->clear; - $layerm->slices->append(Slic3r::Surface->new( - expolygon => $_, - surface_type => S_TYPE_INTERNAL, - )) for @$slices; - } - } - } - } - - # merge all regions' slices to get islands - $layer->make_slices; - } + $self->_slice; # detect slicing errors my $warning_thrown = 0; diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index b68ea6e35..a76adde6a 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -140,6 +140,9 @@ class PrintObject void detect_surfaces_type(); void process_external_surfaces(); void bridge_over_infill(); + coordf_t adjust_layer_height(coordf_t layer_height) const; + std::vector generate_object_layers(coordf_t first_layer_height); + void _slice(); std::vector _slice_region(size_t region_id, std::vector z, bool modifier); void _make_perimeters(); void _infill(); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 1aebd2c37..53e45948e 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -548,6 +548,246 @@ PrintObject::bridge_over_infill() } } +// adjust the layer height to the next multiple of the z full-step resolution +coordf_t PrintObject::adjust_layer_height(coordf_t layer_height) const +{ + coordf_t result = layer_height; + if(this->_print->config.z_steps_per_mm > 0) { + coordf_t min_dz = 1 / this->_print->config.z_steps_per_mm * 4; + result = int(layer_height / min_dz + 0.5) * min_dz; + } + + return result > 0 ? result : layer_height; +} + +// generate a vector of print_z coordinates in object coordinate system (starting with 0) but including +// the first_layer_height if provided. +std::vector PrintObject::generate_object_layers(coordf_t first_layer_height) { + + std::vector result; + + coordf_t min_nozzle_diameter = 1.0; + std::set object_extruders = this->_print->object_extruders(); + for (std::set::const_iterator it_extruder = object_extruders.begin(); it_extruder != object_extruders.end(); ++ it_extruder) { + min_nozzle_diameter = std::min(min_nozzle_diameter, this->_print->config.nozzle_diameter.get_at(*it_extruder)); + } + coordf_t layer_height = std::min(min_nozzle_diameter, this->config.layer_height.getFloat()); + layer_height = this->adjust_layer_height(layer_height); + this->config.layer_height.value = layer_height; + if(first_layer_height) { + result.push_back(first_layer_height); + } + + coordf_t print_z = first_layer_height; + coordf_t height = first_layer_height; + // loop until we have at least one layer and the max slice_z reaches the object height + while (print_z < unscale(this->size.z)) { + height = layer_height; + + // look for an applicable custom range + for (t_layer_height_ranges::const_iterator it_range = this->layer_height_ranges.begin(); it_range != this->layer_height_ranges.end(); ++ it_range) { + if(print_z >= it_range->first.first && print_z <= it_range->first.second) { + if(it_range->second > 0) { + height = it_range->second; + } + } + } + + print_z += height; + + result.push_back(print_z); + } + + // Reduce or thicken the top layer in order to match the original object size. + // This is not actually related to z_steps_per_mm but we only enable it in case + // user provided that value, as it means they really care about the layer height + // accuracy and we don't provide unexpected result for people noticing the last + // layer has a different layer height. + if (this->_print->config.z_steps_per_mm > 0 && result.size() > 1) { + coordf_t diff = result.back() - unscale(this->size.z); + int last_layer = result.size()-1; + + if (diff < 0) { + // we need to thicken last layer + coordf_t new_h = result[last_layer] - result[last_layer-1]; + new_h = std::min(min_nozzle_diameter, new_h - diff); // add (negativ) diff value + std::cout << new_h << std::endl; + result[last_layer] = result[last_layer-1] + new_h; + } else { + // we need to reduce last layer + coordf_t new_h = result[last_layer] - result[last_layer-1]; + if(min_nozzle_diameter/2 < new_h) { //prevent generation of a too small layer + new_h = std::max(min_nozzle_diameter/2, new_h - diff); // subtract (positive) diff value + std::cout << new_h << std::endl; + result[last_layer] = result[last_layer-1] + new_h; + } + } + } + return result; +} + +// 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 PrintObject::_slice() +{ + + coordf_t raft_height = 0; + coordf_t print_z = 0; + coordf_t height = 0; + coordf_t first_layer_height = this->config.first_layer_height.get_abs_value(this->config.layer_height.value); + + + // take raft layers into account + int id = 0; + + if (this->config.raft_layers > 0) { + id = this->config.raft_layers; + + coordf_t min_support_nozzle_diameter = 1.0; + std::set support_material_extruders = this->_print->support_material_extruders(); + for (std::set::const_iterator it_extruder = support_material_extruders.begin(); it_extruder != support_material_extruders.end(); ++ it_extruder) { + min_support_nozzle_diameter = std::min(min_support_nozzle_diameter, this->_print->config.nozzle_diameter.get_at(*it_extruder)); + } + coordf_t support_material_layer_height = 0.75 * min_support_nozzle_diameter; + + // raise first object layer Z by the thickness of the raft itself + // plus the extra distance required by the support material logic + raft_height += first_layer_height; + raft_height += support_material_layer_height * (this->config.raft_layers - 1); + + // reset for later layer generation + first_layer_height = 0; + + // detachable support + if(this->config.support_material_contact_distance > 0) { + first_layer_height = min_support_nozzle_diameter; + raft_height += this->config.support_material_contact_distance; + + } + } + + // Initialize layers and their slice heights. + std::vector slice_zs; + { + this->clear_layers(); + // All print_z values for this object, without the raft. + std::vector object_layers = this->generate_object_layers(first_layer_height); + // Reserve object layers for the raft. Last layer of the raft is the contact layer. + slice_zs.reserve(object_layers.size()); + Layer *prev = nullptr; + coordf_t lo = raft_height; + coordf_t hi = lo; + for (size_t i_layer = 0; i_layer < object_layers.size(); i_layer++) { + lo = hi; // store old value + hi = object_layers[i_layer] + raft_height; + coordf_t slice_z = 0.5 * (lo + hi) - raft_height; + Layer *layer = this->add_layer(id++, hi - lo, hi, slice_z); + slice_zs.push_back(float(slice_z)); + if (prev != nullptr) { + prev->upper_layer = layer; + layer->lower_layer = prev; + } + // Make sure all layers contain layer region objects for all regions. + for (size_t region_id = 0; region_id < this->_print->regions.size(); ++ region_id) + layer->add_region(this->print()->regions[region_id]); + prev = layer; + } + } + + if (this->print()->regions.size() == 1) { + // Optimized for a single region. Slice the single non-modifier mesh. + std::vector expolygons_by_layer = this->_slice_region(0, slice_zs, false); + for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) + this->layers[layer_id]->regions.front()->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal); + } else { + // Slice all non-modifier volumes. + for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) { + std::vector expolygons_by_layer = this->_slice_region(region_id, slice_zs, false); + for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) + this->layers[layer_id]->regions[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal); + } + // Slice all modifier volumes. + for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) { + std::vector expolygons_by_layer = this->_slice_region(region_id, slice_zs, true); + // loop through the other regions and 'steal' the slices belonging to this one + for (size_t other_region_id = 0; other_region_id < this->print()->regions.size(); ++ other_region_id) { + if (region_id == other_region_id) + continue; + for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) { + Layer *layer = layers[layer_id]; + LayerRegion *layerm = layer->regions[region_id]; + LayerRegion *other_layerm = layer->regions[other_region_id]; + if (layerm == nullptr || other_layerm == nullptr) + continue; + Polygons other_slices = to_polygons(other_layerm->slices); + ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id])); + if (my_parts.empty()) + continue; + // Remove such parts from original region. + other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal); + // Append new parts to our region. + layerm->slices.append(std::move(my_parts), stInternal); + } + } + } + } + + // remove last layer(s) if empty + bool done = false; + while (! this->layers.empty()) { + const Layer *layer = this->layers.back(); + for (size_t region_id = 0; region_id < this->print()->regions.size(); ++ region_id) + if (layer->regions[region_id] != nullptr && ! layer->regions[region_id]->slices.empty()) { + done = true; + break; + } + if(done) { + break; + } + this->delete_layer(int(this->layers.size()) - 1); + } + + for (size_t layer_id = 0; layer_id < layers.size(); ++ layer_id) { + Layer *layer = this->layers[layer_id]; + // Apply size compensation and perform clipping of multi-part objects. + float delta = float(scale_(this->config.xy_size_compensation.value)); + bool scale = delta != 0.f; + if (layer->regions.size() == 1) { + if (scale) { + // Single region, growing or shrinking. + LayerRegion *layerm = layer->regions.front(); + layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal); + } + } else if (scale) { + // Multiple regions, growing, shrinking or just clipping one region by the other. + // When clipping the regions, priority is given to the first regions. + Polygons processed; + for (size_t region_id = 0; region_id < layer->regions.size(); ++ region_id) { + LayerRegion *layerm = layer->regions[region_id]; + ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); + if (scale) + slices = offset_ex(slices, delta); + if (region_id > 0) + // Trim by the slices of already processed regions. + slices = diff_ex(to_polygons(std::move(slices)), processed); + if (region_id + 1 < layer->regions.size()) + // Collect the already processed regions to trim the to be processed regions. + processed += to_polygons(slices); + layerm->slices.set(std::move(slices), stInternal); + } + } + // Merge all regions' slices to get islands, chain them by a shortest path. + layer->make_slices(); + } +} + // called from slice() std::vector PrintObject::_slice_region(size_t region_id, std::vector z, bool modifier) diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 895d7e904..867f9a61b 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -62,6 +62,93 @@ to_polygons(const SurfacesConstPtr &surfaces) return pp; } +inline ExPolygons to_expolygons(const Surfaces &src) +{ + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.push_back(it->expolygon); + return expolygons; +} + +inline ExPolygons to_expolygons(Surfaces &&src) +{ + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.emplace_back(ExPolygon(std::move(it->expolygon))); + src.clear(); + return expolygons; +} + +inline ExPolygons to_expolygons(const SurfacesPtr &src) +{ + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.push_back((*it)->expolygon); + return expolygons; +} + + +// Count a nuber of polygons stored inside the vector of expolygons. +// Useful for allocating space for polygons when converting expolygons to polygons. +inline size_t number_polygons(const Surfaces &surfaces) +{ + size_t n_polygons = 0; + for (Surfaces::const_iterator it = surfaces.begin(); it != surfaces.end(); ++ it) + n_polygons += it->expolygon.holes.size() + 1; + return n_polygons; +} + +inline size_t number_polygons(const SurfacesPtr &surfaces) +{ + size_t n_polygons = 0; + for (SurfacesPtr::const_iterator it = surfaces.begin(); it != surfaces.end(); ++ it) + n_polygons += (*it)->expolygon.holes.size() + 1; + return n_polygons; +} + +// Append a vector of Surfaces at the end of another vector of polygons. +inline void polygons_append(Polygons &dst, const Surfaces &src) +{ + dst.reserve(dst.size() + number_polygons(src)); + for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++ it) { + dst.push_back(it->expolygon.contour); + dst.insert(dst.end(), it->expolygon.holes.begin(), it->expolygon.holes.end()); + } +} + +inline void polygons_append(Polygons &dst, Surfaces &&src) +{ + dst.reserve(dst.size() + number_polygons(src)); + for (Surfaces::iterator it = src.begin(); it != src.end(); ++ it) { + dst.push_back(std::move(it->expolygon.contour)); + std::move(std::begin(it->expolygon.holes), std::end(it->expolygon.holes), std::back_inserter(dst)); + it->expolygon.holes.clear(); + } +} + +// Append a vector of Surfaces at the end of another vector of polygons. +inline void polygons_append(Polygons &dst, const SurfacesPtr &src) +{ + dst.reserve(dst.size() + number_polygons(src)); + for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { + dst.push_back((*it)->expolygon.contour); + dst.insert(dst.end(), (*it)->expolygon.holes.begin(), (*it)->expolygon.holes.end()); + } +} + +inline void polygons_append(Polygons &dst, SurfacesPtr &&src) +{ + dst.reserve(dst.size() + number_polygons(src)); + for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { + dst.push_back(std::move((*it)->expolygon.contour)); + std::move(std::begin((*it)->expolygon.holes), std::end((*it)->expolygon.holes), std::back_inserter(dst)); + (*it)->expolygon.holes.clear(); + } +} + } #endif diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/xs/src/libslic3r/SurfaceCollection.hpp index 6c4fe05a7..590ea4aae 100644 --- a/xs/src/libslic3r/SurfaceCollection.hpp +++ b/xs/src/libslic3r/SurfaceCollection.hpp @@ -23,6 +23,16 @@ class SurfaceCollection template bool any_bottom_contains(const T &item) const; SurfacesPtr filter_by_type(SurfaceType type); void filter_by_type(SurfaceType type, Polygons* polygons); + + void set(const SurfaceCollection &coll) { surfaces = coll.surfaces; } + void set(SurfaceCollection &&coll) { surfaces = std::move(coll.surfaces); } + void set(const ExPolygons &src, SurfaceType surfaceType) { clear(); this->append(src, surfaceType); } + void set(const ExPolygons &src, const Surface &surfaceTempl) { clear(); this->append(src, surfaceTempl); } + void set(const Surfaces &src) { clear(); this->append(src); } + void set(ExPolygons &&src, SurfaceType surfaceType) { clear(); this->append(std::move(src), surfaceType); } + void set(ExPolygons &&src, const Surface &surfaceTempl) { clear(); this->append(std::move(src), surfaceTempl); } + void set(Surfaces &&src) { clear(); this->append(std::move(src)); } + void append(const SurfaceCollection &coll); void append(const Surfaces &surfaces); void append(const ExPolygons &src, const Surface &templ); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index c4590a69e..9863cc9af 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -126,6 +126,7 @@ _constant() void detect_surfaces_type(); void process_external_surfaces(); void bridge_over_infill(); + void _slice(); SV* _slice_region(size_t region_id, std::vector z, bool modifier) %code%{ std::vector z_f(z.begin(), z.end());