mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
Merge branch 'master' into lm_warnings
This commit is contained in:
commit
004e2719b1
172 changed files with 9118 additions and 4980 deletions
|
@ -49,7 +49,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta
|
|||
{
|
||||
// Translate meshes so that our toolpath generation algorithms work with smaller
|
||||
// XY coordinates; this translation is an optimization and not strictly required.
|
||||
// A cloned mesh will be aligned to 0 before slicing in _slice_region() since we
|
||||
// A cloned mesh will be aligned to 0 before slicing in slice_region() since we
|
||||
// don't assume it's already aligned and we don't alter the original position in model.
|
||||
// We store the XY translation so that we can place copies correctly in the output G-code
|
||||
// (copies are expressed in G-code coordinates and this translation is not publicly exposed).
|
||||
|
@ -590,7 +590,12 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
|||
|
||||
bool PrintObject::invalidate_all_steps()
|
||||
{
|
||||
return Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
|
||||
// First call the "invalidate" functions, which may cancel background processing.
|
||||
bool result = Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
|
||||
// Then reset some of the depending values.
|
||||
this->m_slicing_params.valid = false;
|
||||
this->region_volumes.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PrintObject::has_support_material() const
|
||||
|
@ -1351,10 +1356,12 @@ PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObject
|
|||
return config;
|
||||
}
|
||||
|
||||
PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders)
|
||||
PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders)
|
||||
{
|
||||
PrintRegionConfig config = default_region_config;
|
||||
normalize_and_apply_config(config, volume.get_object()->config);
|
||||
if (layer_range_config != nullptr)
|
||||
normalize_and_apply_config(config, *layer_range_config);
|
||||
normalize_and_apply_config(config, volume.config);
|
||||
if (! volume.material_id().empty())
|
||||
normalize_and_apply_config(config, volume.material()->config);
|
||||
|
@ -1372,28 +1379,37 @@ void PrintObject::update_slicing_parameters()
|
|||
this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders());
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z)
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z)
|
||||
{
|
||||
PrintConfig print_config;
|
||||
PrintObjectConfig object_config;
|
||||
PrintRegionConfig default_region_config;
|
||||
print_config .apply(full_config, true);
|
||||
object_config.apply(full_config, true);
|
||||
default_region_config.apply(full_config, true);
|
||||
size_t num_extruders = print_config.nozzle_diameter.size();
|
||||
object_config = object_config_from_model_object(object_config, model_object, num_extruders);
|
||||
PrintConfig print_config;
|
||||
PrintObjectConfig object_config;
|
||||
PrintRegionConfig default_region_config;
|
||||
print_config.apply(full_config, true);
|
||||
object_config.apply(full_config, true);
|
||||
default_region_config.apply(full_config, true);
|
||||
size_t num_extruders = print_config.nozzle_diameter.size();
|
||||
object_config = object_config_from_model_object(object_config, model_object, num_extruders);
|
||||
|
||||
std::vector<unsigned int> object_extruders;
|
||||
for (const ModelVolume *model_volume : model_object.volumes)
|
||||
if (model_volume->is_model_part())
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
std::vector<unsigned int> object_extruders;
|
||||
for (const ModelVolume* model_volume : model_object.volumes)
|
||||
if (model_volume->is_model_part()) {
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, nullptr, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range_and_config : model_object.layer_config_ranges)
|
||||
if (range_and_config.second.has("perimeter_extruder") ||
|
||||
range_and_config.second.has("infill_extruder") ||
|
||||
range_and_config.second.has("solid_infill_extruder"))
|
||||
PrintRegion::collect_object_printing_extruders(
|
||||
print_config,
|
||||
region_config_from_model_volume(default_region_config, &range_and_config.second, *model_volume, num_extruders),
|
||||
object_extruders);
|
||||
}
|
||||
sort_remove_duplicates(object_extruders);
|
||||
|
||||
if (object_max_z <= 0.f)
|
||||
object_max_z = model_object.raw_bounding_box().size().z();
|
||||
object_max_z = (float)model_object.raw_bounding_box().size().z();
|
||||
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
|
||||
}
|
||||
|
||||
|
@ -1427,12 +1443,12 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
|
|||
layer_height_profile.clear();
|
||||
|
||||
if (layer_height_profile.empty()) {
|
||||
if (0)
|
||||
if (0)
|
||||
// if (this->layer_height_profile.empty())
|
||||
layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_height_ranges, model_object.volumes);
|
||||
layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
|
||||
else
|
||||
layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_height_ranges);
|
||||
updated = true;
|
||||
layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment
|
||||
updated = true;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
@ -1486,22 +1502,28 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
}
|
||||
|
||||
// Count model parts and modifier meshes, check whether the model parts are of the same region.
|
||||
int single_volume_region = -2; // not set yet
|
||||
int all_volumes_single_region = -2; // not set yet
|
||||
bool has_z_ranges = false;
|
||||
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]) {
|
||||
int last_volume_id = -1;
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const int volume_id = volume_and_range.second;
|
||||
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;
|
||||
if (last_volume_id == volume_id) {
|
||||
has_z_ranges = true;
|
||||
} else {
|
||||
last_volume_id = volume_id;
|
||||
if (all_volumes_single_region == -2)
|
||||
// first model volume met
|
||||
all_volumes_single_region = region_id;
|
||||
else if (all_volumes_single_region != region_id)
|
||||
// multiple volumes met and they are not equal
|
||||
all_volumes_single_region = -1;
|
||||
++ num_volumes;
|
||||
}
|
||||
} else if (model_volume->is_modifier())
|
||||
++ num_modifiers;
|
||||
}
|
||||
|
@ -1511,13 +1533,13 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
// Slice all non-modifier volumes.
|
||||
bool clipped = false;
|
||||
bool upscaled = false;
|
||||
if (! m_config.clip_multipart_objects.value || single_volume_region >= 0) {
|
||||
if (! has_z_ranges && (! m_config.clip_multipart_objects.value || all_volumes_single_region >= 0)) {
|
||||
// Cheap path: Slice regions without mutual clipping.
|
||||
// The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs);
|
||||
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)
|
||||
|
@ -1538,15 +1560,29 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
};
|
||||
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]) {
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
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;
|
||||
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges[j].first.second;
|
||||
else
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
// slicing in parallel
|
||||
sliced_volumes.emplace_back(volume_id, map_volume_to_region[volume_id], this->_slice_volume(slice_zs, *model_volume));
|
||||
}
|
||||
sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, *model_volume));
|
||||
i = j;
|
||||
} else
|
||||
++ i;
|
||||
}
|
||||
}
|
||||
// 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(
|
||||
|
@ -1600,7 +1636,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ 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_modifiers(region_id, slice_zs);
|
||||
m_print->throw_if_canceled();
|
||||
if (expolygons_by_layer.empty())
|
||||
continue;
|
||||
|
@ -1616,7 +1652,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
Layer *layer = m_layers[layer_id];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr)
|
||||
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
|
@ -1749,46 +1785,127 @@ end:
|
|||
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)
|
||||
// To be used only if there are no layer span specific configurations applied, which would lead to z ranges being generated for this region.
|
||||
std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::vector<float> &z) const
|
||||
{
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
if (region_id < this->region_volumes.size()) {
|
||||
for (int volume_id : this->region_volumes[region_id]) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_id];
|
||||
if (modifier ? volume->is_modifier() : volume->is_model_part())
|
||||
volumes.emplace_back(volume);
|
||||
}
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
|
||||
if (volume->is_model_part())
|
||||
volumes.emplace_back(volume);
|
||||
}
|
||||
}
|
||||
return this->_slice_volumes(z, volumes);
|
||||
return this->slice_volumes(z, volumes);
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::slice_support_enforcers() const
|
||||
// Z ranges are not applicable to modifier meshes, therefore a sinle volume will be found in volume_and_range at most once.
|
||||
std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const
|
||||
{
|
||||
std::vector<ExPolygons> out;
|
||||
if (region_id < this->region_volumes.size())
|
||||
{
|
||||
std::vector<std::vector<t_layer_height_range>> volume_ranges;
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
volume_ranges.reserve(volumes_and_ranges.size());
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_modifier()) {
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) {
|
||||
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON)
|
||||
ranges.back().second = volumes_and_ranges[j].first.second;
|
||||
else
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
}
|
||||
volume_ranges.emplace_back(std::move(ranges));
|
||||
i = j;
|
||||
} else
|
||||
++ i;
|
||||
}
|
||||
|
||||
if (! volume_ranges.empty())
|
||||
{
|
||||
bool equal_ranges = true;
|
||||
for (size_t i = 1; i < volume_ranges.size(); ++ i) {
|
||||
assert(! volume_ranges[i].empty());
|
||||
if (volume_ranges.front() != volume_ranges[i]) {
|
||||
equal_ranges = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) {
|
||||
// No modifier in this region was split to layer spans.
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : this->region_volumes[region_id]) {
|
||||
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second];
|
||||
if (volume->is_modifier())
|
||||
volumes.emplace_back(volume);
|
||||
}
|
||||
out = this->slice_volumes(slice_zs, volumes);
|
||||
} else {
|
||||
// Some modifier in this region was split to layer spans.
|
||||
std::vector<char> merge;
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = this->region_volumes[region_id];
|
||||
for (size_t i = 0; i < volumes_and_ranges.size(); ) {
|
||||
int volume_id = volumes_and_ranges[i].second;
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_modifier()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id;
|
||||
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
|
||||
std::vector<t_layer_height_range> ranges;
|
||||
ranges.emplace_back(volumes_and_ranges[i].first);
|
||||
size_t j = i + 1;
|
||||
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j)
|
||||
ranges.emplace_back(volumes_and_ranges[j].first);
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> this_slices = this->slice_volume(slice_zs, ranges, *model_volume);
|
||||
if (out.empty()) {
|
||||
out = std::move(this_slices);
|
||||
merge.assign(out.size(), false);
|
||||
} else {
|
||||
for (size_t i = 0; i < out.size(); ++ i)
|
||||
if (! this_slices[i].empty())
|
||||
if (! out[i].empty()) {
|
||||
append(out[i], this_slices[i]);
|
||||
merge[i] = true;
|
||||
} else
|
||||
out[i] = std::move(this_slices[i]);
|
||||
}
|
||||
i = j;
|
||||
} else
|
||||
++ i;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < merge.size(); ++ i)
|
||||
if (merge[i])
|
||||
out[i] = union_ex(out[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::slice_support_volumes(const ModelVolumeType &model_volume_type) const
|
||||
{
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
for (const ModelVolume *volume : this->model_object()->volumes)
|
||||
if (volume->is_support_enforcer())
|
||||
if (volume->type() == model_volume_type)
|
||||
volumes.emplace_back(volume);
|
||||
std::vector<float> zs;
|
||||
zs.reserve(this->layers().size());
|
||||
for (const Layer *l : this->layers())
|
||||
zs.emplace_back((float)l->slice_z);
|
||||
return this->_slice_volumes(zs, volumes);
|
||||
return this->slice_volumes(zs, volumes);
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::slice_support_blockers() const
|
||||
{
|
||||
std::vector<const ModelVolume*> volumes;
|
||||
for (const ModelVolume *volume : this->model_object()->volumes)
|
||||
if (volume->is_support_blocker())
|
||||
volumes.emplace_back(volume);
|
||||
std::vector<float> zs;
|
||||
zs.reserve(this->layers().size());
|
||||
for (const Layer *l : this->layers())
|
||||
zs.emplace_back((float)l->slice_z);
|
||||
return this->_slice_volumes(zs, volumes);
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const
|
||||
std::vector<ExPolygons> PrintObject::slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const
|
||||
{
|
||||
std::vector<ExPolygons> layers;
|
||||
if (! volumes.empty()) {
|
||||
|
@ -1825,34 +1942,71 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
|||
return layers;
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z, const ModelVolume &volume) const
|
||||
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(), true);
|
||||
if (mesh.repaired) {
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
stl_check_facets_exact(&mesh.stl);
|
||||
if (! z.empty()) {
|
||||
// Compose mesh.
|
||||
//FIXME better to split the mesh into separate shells, perform slicing over each shell separately and then to use a Boolean operation to merge them.
|
||||
TriangleMesh mesh(volume.mesh());
|
||||
mesh.transform(volume.get_matrix(), true);
|
||||
if (mesh.repaired) {
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
stl_check_facets_exact(&mesh.stl);
|
||||
}
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo, true);
|
||||
// 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();});
|
||||
// TriangleMeshSlicer needs the shared vertices.
|
||||
mesh.require_shared_vertices();
|
||||
mslicer.init(&mesh, callback);
|
||||
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
}
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo, true);
|
||||
// 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();});
|
||||
// TriangleMeshSlicer needs the shared vertices.
|
||||
mesh.require_shared_vertices();
|
||||
mslicer.init(&mesh, callback);
|
||||
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
// Filter the zs not inside the ranges. The ranges are closed at the botton and open at the top, they are sorted lexicographically and non overlapping.
|
||||
std::vector<ExPolygons> PrintObject::slice_volume(const std::vector<float> &z, const std::vector<t_layer_height_range> &ranges, const ModelVolume &volume) const
|
||||
{
|
||||
std::vector<ExPolygons> out;
|
||||
if (! z.empty() && ! ranges.empty()) {
|
||||
if (ranges.size() == 1 && z.front() >= ranges.front().first && z.back() < ranges.front().second) {
|
||||
// All layers fit into a single range.
|
||||
out = this->slice_volume(z, volume);
|
||||
} else {
|
||||
std::vector<float> z_filtered;
|
||||
std::vector<std::pair<size_t, size_t>> n_filtered;
|
||||
z_filtered.reserve(z.size());
|
||||
n_filtered.reserve(2 * ranges.size());
|
||||
size_t i = 0;
|
||||
for (const t_layer_height_range &range : ranges) {
|
||||
for (; i < z.size() && z[i] < range.first; ++ i) ;
|
||||
size_t first = i;
|
||||
for (; i < z.size() && z[i] < range.second; ++ i)
|
||||
z_filtered.emplace_back(z[i]);
|
||||
if (i > first)
|
||||
n_filtered.emplace_back(std::make_pair(first, i));
|
||||
}
|
||||
if (! n_filtered.empty()) {
|
||||
std::vector<ExPolygons> layers = this->slice_volume(z_filtered, volume);
|
||||
out.assign(z.size(), ExPolygons());
|
||||
i = 0;
|
||||
for (const std::pair<size_t, size_t> &span : n_filtered)
|
||||
for (size_t j = span.first; j < span.second; ++ j)
|
||||
out[j] = std::move(layers[i ++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string PrintObject::_fix_slicing_errors()
|
||||
{
|
||||
// Collect layers with slicing errors.
|
||||
|
@ -2116,7 +2270,7 @@ void PrintObject::clip_fill_surfaces()
|
|||
//Should the pw not be half of the current value?
|
||||
float pw = FLT_MAX;
|
||||
for (const LayerRegion *layerm : layer->m_regions)
|
||||
pw = std::min<float>(pw, layerm->flow(frPerimeter).scaled_width());
|
||||
pw = std::min(pw, (float)layerm->flow(frPerimeter).scaled_width());
|
||||
// Append such thick perimeters to the areas that need support
|
||||
polygons_append(overhangs, offset2(perimeters, -pw, +pw));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue