mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-30 21:22:01 +08:00
Merge pull request #3796 from platsch/slice_xs
Ported parts of Slice to xs
This commit is contained in:
commit
ff9bae79ca
@ -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;
|
||||
|
@ -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<coordf_t> generate_object_layers(coordf_t first_layer_height);
|
||||
void _slice();
|
||||
std::vector<ExPolygons> _slice_region(size_t region_id, std::vector<float> z, bool modifier);
|
||||
void _make_perimeters();
|
||||
void _infill();
|
||||
|
@ -549,6 +549,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<coordf_t> PrintObject::generate_object_layers(coordf_t first_layer_height) {
|
||||
|
||||
std::vector<coordf_t> result;
|
||||
|
||||
coordf_t min_nozzle_diameter = 1.0;
|
||||
std::set<size_t> object_extruders = this->_print->object_extruders();
|
||||
for (std::set<size_t>::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<size_t> support_material_extruders = this->_print->support_material_extruders();
|
||||
for (std::set<size_t>::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<float> slice_zs;
|
||||
{
|
||||
this->clear_layers();
|
||||
// All print_z values for this object, without the raft.
|
||||
std::vector<coordf_t> 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> 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> 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> 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<ExPolygons>
|
||||
PrintObject::_slice_region(size_t region_id, std::vector<float> z, bool modifier)
|
||||
|
@ -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
|
||||
|
@ -23,6 +23,16 @@ class SurfaceCollection
|
||||
template <class T> 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);
|
||||
|
@ -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<double> z, bool modifier)
|
||||
%code%{
|
||||
std::vector<float> z_f(z.begin(), z.end());
|
||||
|
Loading…
x
Reference in New Issue
Block a user