mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
Implemented clipping of parts of multi-part objects in the order
they are presented in the UI. Parallelized the slice stealing when splitting regions with modifier meshes. Rewrote Layer::make_perimeters() to C++11 loops.
This commit is contained in:
parent
c1a24d2fbb
commit
e399cf6d3d
3 changed files with 177 additions and 51 deletions
|
@ -105,13 +105,14 @@ void Layer::make_perimeters()
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
|
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
|
||||||
|
|
||||||
// keep track of regions whose perimeters we have already generated
|
// keep track of regions whose perimeters we have already generated
|
||||||
std::set<size_t> done;
|
std::vector<unsigned char> done(m_regions.size(), false);
|
||||||
|
|
||||||
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) {
|
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) {
|
||||||
size_t region_id = layerm - m_regions.begin();
|
size_t region_id = layerm - m_regions.begin();
|
||||||
if (done.find(region_id) != done.end()) continue;
|
if (done[region_id])
|
||||||
|
continue;
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||||
done.insert(region_id);
|
done[region_id] = true;
|
||||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||||
|
|
||||||
// find compatible regions
|
// find compatible regions
|
||||||
|
@ -131,7 +132,7 @@ void Layer::make_perimeters()
|
||||||
&& config.thin_walls == other_config.thin_walls
|
&& config.thin_walls == other_config.thin_walls
|
||||||
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||||
layerms.push_back(other_layerm);
|
layerms.push_back(other_layerm);
|
||||||
done.insert(it - m_regions.begin());
|
done[it - m_regions.begin()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,15 +144,13 @@ void Layer::make_perimeters()
|
||||||
SurfaceCollection new_slices;
|
SurfaceCollection new_slices;
|
||||||
{
|
{
|
||||||
// group slices (surfaces) according to number of extra perimeters
|
// group slices (surfaces) according to number of extra perimeters
|
||||||
std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
for (LayerRegion *layerm : layerms)
|
||||||
for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
|
for (Surface &surface : layerm->slices.surfaces)
|
||||||
slices[s->extra_perimeters].push_back(*s);
|
slices[surface.extra_perimeters].emplace_back(surface);
|
||||||
}
|
|
||||||
}
|
|
||||||
// merge the surfaces assigned to each group
|
// merge the surfaces assigned to each group
|
||||||
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it)
|
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||||
new_slices.append(union_ex(it->second, true), it->second.front());
|
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
// make perimeters
|
// make perimeters
|
||||||
|
|
|
@ -203,6 +203,7 @@ private:
|
||||||
|
|
||||||
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
||||||
std::vector<ExPolygons> _slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const;
|
std::vector<ExPolygons> _slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const;
|
||||||
|
std::vector<ExPolygons> _slice_volume(const std::vector<float> &z, const ModelVolume &volume) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WipeTowerData
|
struct WipeTowerData
|
||||||
|
|
|
@ -810,7 +810,7 @@ void PrintObject::process_external_surfaces()
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||||
m_layers[layer_idx]->get_region(region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1480,46 +1480,151 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||||
prev = layer;
|
prev = layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count model parts and modifier meshes, check whether the model parts are of the same region.
|
||||||
|
int single_volume_region = -2; // not set yet
|
||||||
|
size_t num_volumes = 0;
|
||||||
|
size_t num_modifiers = 0;
|
||||||
|
std::vector<int> map_volume_to_region(this->model_object()->volumes.size());
|
||||||
|
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||||
|
for (int volume_id : this->region_volumes[region_id]) {
|
||||||
|
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||||
|
if (model_volume->is_model_part()) {
|
||||||
|
map_volume_to_region[volume_id] = region_id;
|
||||||
|
if (single_volume_region == -2)
|
||||||
|
// first model volume met
|
||||||
|
single_volume_region = region_id;
|
||||||
|
else if (single_volume_region != region_id)
|
||||||
|
// multiple volumes met and they are not equal
|
||||||
|
single_volume_region = -1;
|
||||||
|
++ num_volumes;
|
||||||
|
} else if (model_volume->is_modifier())
|
||||||
|
++ num_modifiers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(num_volumes > 0);
|
||||||
|
|
||||||
// Slice all non-modifier volumes.
|
// Slice all non-modifier volumes.
|
||||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
bool clipped = false;
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
bool upscaled = false;
|
||||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
if (! m_config.clip_multipart_objects.value || single_volume_region >= 0) {
|
||||||
m_print->throw_if_canceled();
|
// Cheap path: Slice regions without mutual clipping.
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
// The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
|
||||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal);
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||||
m_print->throw_if_canceled();
|
// slicing in parallel
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||||
|
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||||
|
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal);
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Expensive path: Slice one volume after the other in the order they are presented at the user interface,
|
||||||
|
// clip the last volumes with the first.
|
||||||
|
// First slice the volumes.
|
||||||
|
struct SlicedVolume {
|
||||||
|
SlicedVolume(int volume_id, int region_id, std::vector<ExPolygons> &&expolygons_by_layer) :
|
||||||
|
volume_id(volume_id), region_id(region_id), expolygons_by_layer(std::move(expolygons_by_layer)) {}
|
||||||
|
int volume_id;
|
||||||
|
int region_id;
|
||||||
|
std::vector<ExPolygons> expolygons_by_layer;
|
||||||
|
};
|
||||||
|
std::vector<SlicedVolume> sliced_volumes;
|
||||||
|
sliced_volumes.reserve(num_volumes);
|
||||||
|
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||||
|
for (int volume_id : this->region_volumes[region_id]) {
|
||||||
|
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||||
|
if (model_volume->is_model_part()) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
|
||||||
|
// slicing in parallel
|
||||||
|
sliced_volumes.emplace_back(volume_id, map_volume_to_region[volume_id], this->_slice_volume(slice_zs, *model_volume));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Second clip the volumes in the order they are presented at the user interface.
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - start";
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, slice_zs.size()),
|
||||||
|
[this, &sliced_volumes, num_modifiers](const tbb::blocked_range<size_t>& range) {
|
||||||
|
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||||
|
// Only upscale together with clipping if there are no modifiers, as the modifiers shall be applied before upscaling
|
||||||
|
// (upscaling may grow the object outside of the modifier mesh).
|
||||||
|
bool upscale = delta > 0 && num_modifiers == 0;
|
||||||
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
// Trim volumes in a single layer, one by the other, possibly apply upscaling.
|
||||||
|
{
|
||||||
|
Polygons processed;
|
||||||
|
for (SlicedVolume &sliced_volume : sliced_volumes) {
|
||||||
|
ExPolygons slices = std::move(sliced_volume.expolygons_by_layer[layer_id]);
|
||||||
|
if (upscale)
|
||||||
|
slices = offset_ex(std::move(slices), delta);
|
||||||
|
if (! processed.empty())
|
||||||
|
// Trim by the slices of already processed regions.
|
||||||
|
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||||
|
if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
|
||||||
|
// Collect the already processed regions to trim the to be processed regions.
|
||||||
|
polygons_append(processed, slices);
|
||||||
|
sliced_volume.expolygons_by_layer[layer_id] = std::move(slices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Collect and union volumes of a single region.
|
||||||
|
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||||
|
ExPolygons expolygons;
|
||||||
|
size_t num_volumes = 0;
|
||||||
|
for (SlicedVolume &sliced_volume : sliced_volumes)
|
||||||
|
if (sliced_volume.region_id == region_id && ! sliced_volume.expolygons_by_layer[layer_id].empty()) {
|
||||||
|
++ num_volumes;
|
||||||
|
append(expolygons, std::move(sliced_volume.expolygons_by_layer[layer_id]));
|
||||||
|
}
|
||||||
|
if (num_volumes > 1)
|
||||||
|
// Merge the islands using a positive / negative offset.
|
||||||
|
expolygons = offset_ex(offset_ex(expolygons, float(scale_(EPSILON))), -float(scale_(EPSILON)));
|
||||||
|
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stInternal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - end";
|
||||||
|
clipped = true;
|
||||||
|
upscaled = m_config.xy_size_compensation.value > 0 && num_modifiers == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice all modifier volumes.
|
// Slice all modifier volumes.
|
||||||
if (this->region_volumes.size() > 1) {
|
if (this->region_volumes.size() > 1) {
|
||||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
|
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
|
||||||
|
// slicing in parallel
|
||||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, true);
|
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, true);
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
|
if (expolygons_by_layer.empty())
|
||||||
|
continue;
|
||||||
// loop through the other regions and 'steal' the slices belonging to this one
|
// loop through the other regions and 'steal' the slices belonging to this one
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " start";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " start";
|
||||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
tbb::parallel_for(
|
||||||
if (region_id == other_region_id)
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
continue;
|
[this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) {
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
Layer *layer = m_layers[layer_id];
|
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||||
LayerRegion *layerm = layer->m_regions[region_id];
|
if (region_id == other_region_id)
|
||||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
continue;
|
||||||
if (layerm == nullptr || other_layerm == nullptr)
|
Layer *layer = m_layers[layer_id];
|
||||||
continue;
|
LayerRegion *layerm = layer->m_regions[region_id];
|
||||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
if (layerm == nullptr || other_layerm == nullptr)
|
||||||
if (my_parts.empty())
|
continue;
|
||||||
continue;
|
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||||
// Remove such parts from original region.
|
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
if (my_parts.empty())
|
||||||
// Append new parts to our region.
|
continue;
|
||||||
layerm->slices.append(std::move(my_parts), stInternal);
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " end";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " end";
|
||||||
}
|
}
|
||||||
|
@ -1542,7 +1647,7 @@ end:
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
||||||
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, upscaled, clipped](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
Layer *layer = m_layers[layer_id];
|
Layer *layer = m_layers[layer_id];
|
||||||
|
@ -1569,8 +1674,8 @@ end:
|
||||||
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
||||||
// Apply the elephant foot compensation.
|
// Apply the elephant foot compensation.
|
||||||
if (elephant_foot_compensation > 0) {
|
if (elephant_foot_compensation > 0) {
|
||||||
float elephant_foot_spacing = layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing();
|
float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
|
||||||
float external_perimeter_nozzle = scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1));
|
float external_perimeter_nozzle = float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
||||||
size_t nsteps = size_t(steps);
|
size_t nsteps = size_t(steps);
|
||||||
|
@ -1584,9 +1689,8 @@ end:
|
||||||
layerm->slices.set(std::move(expolygons), stInternal);
|
layerm->slices.set(std::move(expolygons), stInternal);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool upscale = delta > 0.f;
|
bool upscale = ! upscaled && delta > 0.f;
|
||||||
bool downscale = delta < 0.f || elephant_foot_compensation > 0.f;
|
bool clip = ! clipped && m_config.clip_multipart_objects.value;
|
||||||
bool clip = m_config.clip_multipart_objects.value;
|
|
||||||
if (upscale || clip) {
|
if (upscale || clip) {
|
||||||
// Multiple regions, growing or just clipping one region by the other.
|
// Multiple regions, growing or just clipping one region by the other.
|
||||||
// When clipping the regions, priority is given to the first regions.
|
// When clipping the regions, priority is given to the first regions.
|
||||||
|
@ -1607,7 +1711,7 @@ end:
|
||||||
}
|
}
|
||||||
if (delta < 0.f) {
|
if (delta < 0.f) {
|
||||||
// Apply the negative XY compensation.
|
// Apply the negative XY compensation.
|
||||||
Polygons trimming = offset(layer->merged(EPSILON), delta - EPSILON);
|
Polygons trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON));
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||||
layer->m_regions[region_id]->trim_surfaces(trimming);
|
layer->m_regions[region_id]->trim_surfaces(trimming);
|
||||||
}
|
}
|
||||||
|
@ -1618,8 +1722,8 @@ end:
|
||||||
float external_perimeter_nozzle = 0.f;
|
float external_perimeter_nozzle = 0.f;
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||||
LayerRegion *layerm = layer->m_regions[region_id];
|
LayerRegion *layerm = layer->m_regions[region_id];
|
||||||
elephant_foot_spacing.emplace_back(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
|
elephant_foot_spacing.emplace_back(float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing()));
|
||||||
external_perimeter_nozzle += scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1));
|
external_perimeter_nozzle += float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||||
}
|
}
|
||||||
external_perimeter_nozzle /= (float)layer->m_regions.size();
|
external_perimeter_nozzle /= (float)layer->m_regions.size();
|
||||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||||
|
@ -1627,7 +1731,7 @@ end:
|
||||||
size_t nsteps = size_t(steps);
|
size_t nsteps = size_t(steps);
|
||||||
float step = elephant_foot_compensation / steps;
|
float step = elephant_foot_compensation / steps;
|
||||||
for (size_t i = 0; i < nsteps; ++ i) {
|
for (size_t i = 0; i < nsteps; ++ i) {
|
||||||
Polygons trimming_polygons = offset(layer->merged(EPSILON), - step - EPSILON);
|
Polygons trimming_polygons = offset(layer->merged(float(EPSILON)), - step - float(EPSILON));
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||||
layer->m_regions[region_id]->elephant_foot_compensation_step(elephant_foot_spacing[region_id] + step, trimming_polygons);
|
layer->m_regions[region_id]->elephant_foot_compensation_step(elephant_foot_spacing[region_id] + step, trimming_polygons);
|
||||||
}
|
}
|
||||||
|
@ -1709,6 +1813,28 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z, const ModelVolume &volume) const
|
||||||
|
{
|
||||||
|
std::vector<ExPolygons> layers;
|
||||||
|
// Compose mesh.
|
||||||
|
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||||
|
TriangleMesh mesh(volume.mesh);
|
||||||
|
mesh.transform(volume.get_matrix());
|
||||||
|
if (mesh.stl.stats.number_of_facets > 0) {
|
||||||
|
mesh.transform(m_trafo);
|
||||||
|
// apply XY shift
|
||||||
|
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
|
||||||
|
// perform actual slicing
|
||||||
|
TriangleMeshSlicer mslicer;
|
||||||
|
const Print *print = this->print();
|
||||||
|
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
||||||
|
mslicer.init(&mesh, callback);
|
||||||
|
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
}
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
|
||||||
std::string PrintObject::_fix_slicing_errors()
|
std::string PrintObject::_fix_slicing_errors()
|
||||||
{
|
{
|
||||||
// Collect layers with slicing errors.
|
// Collect layers with slicing errors.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue