mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 17:55:56 +08:00
WIP Tree Supports: Ported parallelization from cura homebrew parallel_for
to thread building blocks tbb::parallel_for.
This commit is contained in:
parent
f6ae93366a
commit
6e1e4fcca2
@ -9,6 +9,9 @@
|
||||
#include "TreeModelVolumes.hpp"
|
||||
#include "TreeSupport.hpp"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/task_group.h>
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
@ -71,20 +74,22 @@ TreeModelVolumes::TreeModelVolumes(const SliceDataStorage& storage, const coord_
|
||||
{
|
||||
SliceMeshStorage mesh = storage.meshes[mesh_idx];
|
||||
|
||||
cura::parallel_for<LayerIndex>(0, LayerIndex(layer_outlines_[mesh_to_layeroutline_idx[mesh_idx]].second.size()), 1,
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, layer_outlines_[mesh_to_layeroutline_idx[mesh_idx]].second.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
if (mesh.layer_nr_max_filled_layer < layer_idx)
|
||||
{
|
||||
return; // cant break as parallel_for wont allow it, this is equivalent to a continue
|
||||
}
|
||||
Polygons outline = extractOutlineFromMesh(mesh, layer_idx);
|
||||
layer_outlines_[mesh_to_layeroutline_idx[mesh_idx]].second[layer_idx].add(outline);
|
||||
}
|
||||
});
|
||||
}
|
||||
cura::parallel_for<LayerIndex>(0, LayerIndex(anti_overhang_.size()), 1,
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, anti_overhang_.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
if (layer_idx < coord_t(additional_excluded_areas.size()))
|
||||
{
|
||||
anti_overhang_[layer_idx].add(additional_excluded_areas[layer_idx]);
|
||||
@ -100,11 +105,16 @@ TreeModelVolumes::TreeModelVolumes(const SliceDataStorage& storage, const coord_
|
||||
anti_overhang_[layer_idx].add(layer_idx == 0 ? storage.primeTower.outer_poly_first_layer : storage.primeTower.outer_poly);
|
||||
}
|
||||
anti_overhang_[layer_idx] = anti_overhang_[layer_idx].unionPolygons();
|
||||
}
|
||||
});
|
||||
|
||||
for (size_t idx = 0; idx < layer_outlines_.size(); idx++)
|
||||
{
|
||||
cura::parallel_for<LayerIndex>(0, LayerIndex(anti_overhang_.size()), 1, [&](const LayerIndex layer_idx) { layer_outlines_[idx].second[layer_idx] = layer_outlines_[idx].second[layer_idx].unionPolygons(); });
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, anti_overhang_.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||
layer_outlines_[idx].second[layer_idx] = layer_outlines_[idx].second[layer_idx].unionPolygons();
|
||||
});
|
||||
}
|
||||
radius_0 = config.getRadius(0);
|
||||
}
|
||||
@ -199,21 +209,15 @@ void TreeModelVolumes::precalculate(coord_t max_layer)
|
||||
|
||||
// ### Calculate the relevant avoidances in parallel as far as possible
|
||||
{
|
||||
std::future<void> placeable_waiter;
|
||||
tbb::task_group task_group;
|
||||
task_group.run([this, relevant_avoidance_radiis]{ calculateAvoidance(relevant_avoidance_radiis); });
|
||||
task_group.run([this, relevant_avoidance_radiis]{ calculateWallRestrictions(relevant_avoidance_radiis); });
|
||||
if (support_rests_on_model)
|
||||
{
|
||||
placeable_waiter = calculatePlaceables(relevant_avoidance_radiis_to_model);
|
||||
}
|
||||
std::future<void> avoidance_waiter = calculateAvoidance(relevant_avoidance_radiis);
|
||||
std::future<void> wall_restriction_waiter = calculateWallRestrictions(relevant_avoidance_radiis);
|
||||
if (support_rests_on_model)
|
||||
{
|
||||
placeable_waiter.wait();
|
||||
std::future<void> avoidance_model_waiter = calculateAvoidanceToModel(relevant_avoidance_radiis_to_model);
|
||||
avoidance_model_waiter.wait();
|
||||
}
|
||||
avoidance_waiter.wait();
|
||||
wall_restriction_waiter.wait();
|
||||
task_group.run([this, relevant_avoidance_radiis_to_model]{
|
||||
calculatePlaceables(relevant_avoidance_radiis_to_model);
|
||||
calculateAvoidanceToModel(relevant_avoidance_radiis_to_model);
|
||||
});
|
||||
task_group.wait();
|
||||
}
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
auto dur_col = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_coll - t_start).count();
|
||||
@ -549,9 +553,9 @@ LayerIndex TreeModelVolumes::getMaxCalculatedLayer(coord_t radius, const std::un
|
||||
|
||||
void TreeModelVolumes::calculateCollision(std::deque<RadiusLayerPair> keys)
|
||||
{
|
||||
cura::parallel_for<size_t>(0, keys.size(), 1,
|
||||
[&](const size_t i)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, keys.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t i = range.begin(); i < range.end(); ++ i) {
|
||||
coord_t radius = keys[i].first;
|
||||
RadiusLayerPair key(radius, 0);
|
||||
std::unordered_map<RadiusLayerPair, Polygons> data_outer;
|
||||
@ -680,6 +684,7 @@ void TreeModelVolumes::calculateCollision(std::deque<RadiusLayerPair> keys)
|
||||
placeable_areas_cache_.insert(data_placeable_outer.begin(), data_placeable_outer.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
void TreeModelVolumes::calculateCollisionHolefree(std::deque<RadiusLayerPair> keys)
|
||||
@ -690,9 +695,9 @@ void TreeModelVolumes::calculateCollisionHolefree(std::deque<RadiusLayerPair> ke
|
||||
max_layer = std::max(max_layer, keys[i].second);
|
||||
}
|
||||
|
||||
cura::parallel_for<LayerIndex>(0, max_layer + 1, 1,
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, max_layer + 1),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
std::unordered_map<RadiusLayerPair, Polygons> data;
|
||||
for (RadiusLayerPair key : keys)
|
||||
{
|
||||
@ -708,6 +713,7 @@ void TreeModelVolumes::calculateCollisionHolefree(std::deque<RadiusLayerPair> ke
|
||||
std::lock_guard<std::mutex> critical_section(*critical_collision_cache_holefree_);
|
||||
collision_cache_holefree_.insert(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -728,13 +734,13 @@ Polygons TreeModelVolumes::safeOffset(const Polygons& me, coord_t distance, Clip
|
||||
return ret.unionPolygons(collision);
|
||||
}
|
||||
|
||||
std::future<void> TreeModelVolumes::calculateAvoidance(std::deque<RadiusLayerPair> keys)
|
||||
void TreeModelVolumes::calculateAvoidance(std::deque<RadiusLayerPair> keys)
|
||||
{
|
||||
// For every RadiusLayer pair there are 3 avoidances that have to be calculate, calculated in the same paralell_for loop for better paralellisation.
|
||||
const std::vector<AvoidanceType> all_types = { AvoidanceType::SLOW, AvoidanceType::FAST_SAFE, AvoidanceType::FAST };
|
||||
std::future<void> ret = cura::parallel_for_nowait<size_t>(0, keys.size() * 3, 1,
|
||||
[&, keys, all_types](const size_t iter_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, keys.size() * 3),
|
||||
[&, keys, all_types](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t iter_idx = range.begin(); iter_idx < range.end(); ++ iter_idx) {
|
||||
size_t key_idx = iter_idx / 3;
|
||||
{
|
||||
size_t type_idx = iter_idx % all_types.size();
|
||||
@ -804,15 +810,16 @@ std::future<void> TreeModelVolumes::calculateAvoidance(std::deque<RadiusLayerPai
|
||||
(slow ? avoidance_cache_slow_ : holefree ? avoidance_cache_hole_ : avoidance_cache_).insert(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::future<void> TreeModelVolumes::calculatePlaceables(std::deque<RadiusLayerPair> keys)
|
||||
void TreeModelVolumes::calculatePlaceables(std::deque<RadiusLayerPair> keys)
|
||||
{
|
||||
std::future<void> ret = cura::parallel_for_nowait<size_t>(0, keys.size(), 1,
|
||||
[&, keys](const size_t key_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, keys.size()),
|
||||
[&, keys](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t key_idx = range.begin(); key_idx < range.end(); ++ key_idx) {
|
||||
const coord_t radius = keys[key_idx].first;
|
||||
const LayerIndex max_required_layer = keys[key_idx].second;
|
||||
std::vector<std::pair<RadiusLayerPair, Polygons>> data(max_required_layer + 1, std::pair<RadiusLayerPair, Polygons>(RadiusLayerPair(radius, -1), Polygons()));
|
||||
@ -859,18 +866,19 @@ std::future<void> TreeModelVolumes::calculatePlaceables(std::deque<RadiusLayerPa
|
||||
std::lock_guard<std::mutex> critical_section(*critical_placeable_areas_cache_);
|
||||
placeable_areas_cache_.insert(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::future<void> TreeModelVolumes::calculateAvoidanceToModel(std::deque<RadiusLayerPair> keys)
|
||||
void TreeModelVolumes::calculateAvoidanceToModel(std::deque<RadiusLayerPair> keys)
|
||||
{
|
||||
// For every RadiusLayer pair there are 3 avoidances that have to be calculated, calculated in the same parallel_for loop for better parallelization.
|
||||
const std::vector<AvoidanceType> all_types = { AvoidanceType::SLOW, AvoidanceType::FAST_SAFE, AvoidanceType::FAST };
|
||||
std::future<void> ret = cura::parallel_for_nowait<size_t>(0, keys.size() * 3, 1,
|
||||
[&, keys, all_types](const size_t iter_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, keys.size() * 3),
|
||||
[&, keys, all_types](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t iter_idx = range.begin(); iter_idx < range.end(); ++ iter_idx) {
|
||||
size_t key_idx = iter_idx / 3;
|
||||
size_t type_idx = iter_idx % all_types.size();
|
||||
AvoidanceType type = all_types[type_idx];
|
||||
@ -940,13 +948,14 @@ std::future<void> TreeModelVolumes::calculateAvoidanceToModel(std::deque<RadiusL
|
||||
std::lock_guard<std::mutex> critical_section(*(slow ? critical_avoidance_cache_to_model_slow_ : holefree ? critical_avoidance_cache_holefree_to_model_ : critical_avoidance_cache_to_model_));
|
||||
(slow ? avoidance_cache_to_model_slow_ : holefree ? avoidance_cache_hole_to_model_ : avoidance_cache_to_model_).insert(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::future<void> TreeModelVolumes::calculateWallRestrictions(std::deque<RadiusLayerPair> keys)
|
||||
void TreeModelVolumes::calculateWallRestrictions(std::deque<RadiusLayerPair> keys)
|
||||
{
|
||||
// Wall restrictions are mainly important when they represent actual walls that are printed, and not "just" the configured z_distance, because technically valid placement is no excuse for moving through a wall.
|
||||
// As they exist to prevent accidentially moving though a wall at high speed between layers like thie (x = wall,i = influence area,o= empty space,d = blocked area because of z distance) Assume maximum movement distance is two characters and maximum safe movement distance of one character
|
||||
@ -983,9 +992,9 @@ std::future<void> TreeModelVolumes::calculateWallRestrictions(std::deque<RadiusL
|
||||
* layer z-1: ixiiiiiiiiiii
|
||||
*/
|
||||
|
||||
std::future<void> ret = cura::parallel_for_nowait<size_t>(0, keys.size(), 1,
|
||||
[&, keys](const size_t key_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, keys.size()),
|
||||
[&, keys](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t key_idx = range.begin(); key_idx < range.end(); ++ key_idx) {
|
||||
coord_t radius = keys[key_idx].first;
|
||||
RadiusLayerPair key(radius, 0);
|
||||
coord_t min_layer_bottom;
|
||||
@ -1025,6 +1034,7 @@ std::future<void> TreeModelVolumes::calculateWallRestrictions(std::deque<RadiusL
|
||||
std::lock_guard<std::mutex> critical_section(*critical_wall_restrictions_cache_min_);
|
||||
wall_restrictions_cache_min_.insert(data_min.begin(), data_min.end());
|
||||
}
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
@ -196,9 +196,8 @@ class TreeModelVolumes
|
||||
* The result is a 2D area that would cause nodes of radius \p radius to
|
||||
* collide with the model. Result is saved in the cache.
|
||||
* \param keys RadiusLayerPairs of all requested areas. Every radius will be calculated up to the provided layer.
|
||||
* \return A future that has to be waited on
|
||||
*/
|
||||
[[nodiscard]] std::future<void> calculateAvoidance(std::deque<RadiusLayerPair> keys);
|
||||
void calculateAvoidance(std::deque<RadiusLayerPair> keys);
|
||||
|
||||
/*!
|
||||
* \brief Creates the areas that have to be avoided by the tree's branches to prevent collision with the model.
|
||||
@ -226,10 +225,8 @@ class TreeModelVolumes
|
||||
* \brief Creates the areas where a branch of a given radius can be placed on the model.
|
||||
* Result is saved in the cache.
|
||||
* \param keys RadiusLayerPair of the requested areas. The radius will be calculated up to the provided layer.
|
||||
*
|
||||
* \return A future that has to be waited on
|
||||
*/
|
||||
[[nodiscard]] std::future<void> calculatePlaceables(std::deque<RadiusLayerPair> keys);
|
||||
void calculatePlaceables(std::deque<RadiusLayerPair> keys);
|
||||
|
||||
/*!
|
||||
* \brief Creates the areas that have to be avoided by the tree's branches to prevent collision with the model without being able to place a branch with given radius on a single layer.
|
||||
@ -237,10 +234,8 @@ class TreeModelVolumes
|
||||
* The result is a 2D area that would cause nodes of radius \p radius to
|
||||
* collide with the model in a not wanted way. Result is saved in the cache.
|
||||
* \param keys RadiusLayerPairs of all requested areas. Every radius will be calculated up to the provided layer.
|
||||
*
|
||||
* \return A future that has to be waited on
|
||||
*/
|
||||
[[nodiscard]] std::future<void> calculateAvoidanceToModel(std::deque<RadiusLayerPair> keys);
|
||||
void calculateAvoidanceToModel(std::deque<RadiusLayerPair> keys);
|
||||
|
||||
/*!
|
||||
* \brief Creates the areas that have to be avoided by the tree's branches to prevent collision with the model without being able to place a branch with given radius on a single layer.
|
||||
@ -259,10 +254,8 @@ class TreeModelVolumes
|
||||
* These areas are at least xy_min_dist wide. When calculating it is always assumed that every wall is printed on top of another (as in has an overlap with the wall a layer below). Result is saved in the corresponding cache.
|
||||
*
|
||||
* \param keys RadiusLayerPairs of all requested areas. Every radius will be calculated up to the provided layer.
|
||||
*
|
||||
* \return A future that has to be waited on
|
||||
*/
|
||||
[[nodiscard]] std::future<void> calculateWallRestrictions(std::deque<RadiusLayerPair> keys);
|
||||
void calculateWallRestrictions(std::deque<RadiusLayerPair> keys);
|
||||
|
||||
/*!
|
||||
* \brief Creates the areas that can not be passed when expanding an area downwards. As such these areas are an somewhat abstract representation of a wall (as in a printed object).
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <string>
|
||||
#include <windows.h> //todo Remove! ONLY FOR PUBLIC BETA!!
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
@ -140,9 +142,9 @@ void TreeSupport::generateSupportAreas(SliceDataStorage& storage)
|
||||
std::vector<Polygons> exclude(storage.support.supportLayers.size());
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
// get all already existing support areas and exclude them
|
||||
cura::parallel_for<LayerIndex>(LayerIndex(0), LayerIndex(storage.support.supportLayers.size()), LayerIndex(1),
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, storage.support.supportLayers.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
Polygons exlude_at_layer;
|
||||
exlude_at_layer.add(storage.support.supportLayers[layer_idx].support_bottom);
|
||||
exlude_at_layer.add(storage.support.supportLayers[layer_idx].support_roof);
|
||||
@ -151,6 +153,7 @@ void TreeSupport::generateSupportAreas(SliceDataStorage& storage)
|
||||
exlude_at_layer.add(part.outline);
|
||||
}
|
||||
exclude[layer_idx] = exlude_at_layer.unionPolygons();
|
||||
}
|
||||
});
|
||||
config = processing.first; // this struct is used to easy retrieve setting. No other function except those in TreeModelVolumes and generateInitialAreas have knowledge of the existence of multiple meshes being processed.
|
||||
progress_multiplier = 1.0 / double(grouped_meshes.size());
|
||||
@ -701,9 +704,10 @@ void TreeSupport::generateInitialAreas(const SliceMeshStorage& mesh, std::vector
|
||||
|
||||
|
||||
std::mutex critical_sections;
|
||||
cura::parallel_for<LayerIndex>(1, mesh.overhang_areas.size() - z_distance_delta, 1,
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, mesh.overhang_areas.size() - z_distance_delta),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
|
||||
if (mesh.overhang_areas[layer_idx + z_distance_delta].empty())
|
||||
{
|
||||
return; // This is a continue if imagined in a loop context
|
||||
@ -987,6 +991,7 @@ void TreeSupport::generateInitialAreas(const SliceMeshStorage& mesh, std::vector
|
||||
addLinesAsInfluenceAreas(overhang_lines, force_tip_to_roof ? support_roof_layers - dtt_roof : 0, layer_idx - dtt_roof, dtt_roof > 0, roof_enabled ? support_roof_layers - dtt_roof : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
delete cross_fill_provider;
|
||||
@ -1285,14 +1290,18 @@ void TreeSupport::mergeInfluenceAreas(std::unordered_map<SupportElement, Polygon
|
||||
|
||||
// precalculate the AABBs from the influence areas.
|
||||
|
||||
cura::parallel_for<size_t>(1, buckets_area.size(), 2,
|
||||
[&](const size_t idx) // +=2 as in the beginning only uneven buckets will be filled
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, bucket_count),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t idx = range.begin(); idx < range.end(); ++ idx) {
|
||||
{
|
||||
for (const std::pair<SupportElement, Polygons>& input_pair : buckets_area[idx])
|
||||
// +=2 as in the beginning only uneven buckets will be filled
|
||||
size_t bucket_idx = 2 * idx + 1;
|
||||
for (const std::pair<SupportElement, Polygons>& input_pair : buckets_area[bucket_idx])
|
||||
{
|
||||
AABB outer_support_wall_aabb = AABB(input_pair.second);
|
||||
outer_support_wall_aabb.expand(config.getRadius(input_pair.first));
|
||||
buckets_aabb[idx].emplace(input_pair.first, outer_support_wall_aabb);
|
||||
buckets_aabb[bucket_idx].emplace(input_pair.first, outer_support_wall_aabb);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1305,13 +1314,15 @@ void TreeSupport::mergeInfluenceAreas(std::unordered_map<SupportElement, Polygon
|
||||
std::vector<std::vector<SupportElement>> erase(buckets_area.size() / 2);
|
||||
|
||||
|
||||
cura::parallel_for<size_t>(0, (coord_t)buckets_area.size() - 1, 2,
|
||||
[&](const size_t bucket_pair_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, buckets_area.size() / 2),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t idx = range.begin(); idx < range.end(); ++ idx) {
|
||||
const size_t bucket_pair_idx = idx * 2;
|
||||
// Merge bucket_count adjacent to each other, merging uneven bucket numbers into even buckets
|
||||
mergeHelper(buckets_aabb[bucket_pair_idx], buckets_aabb[bucket_pair_idx + 1], to_bp_areas, to_model_areas, influence_areas, insert_main[bucket_pair_idx / 2], insert_secondary[bucket_pair_idx / 2], insert_influence[bucket_pair_idx / 2], erase[bucket_pair_idx / 2], layer_idx);
|
||||
buckets_area[bucket_pair_idx + 1].clear(); // clear now irrelevant max_bucket_count, and delete them later
|
||||
buckets_aabb[bucket_pair_idx + 1].clear();
|
||||
}
|
||||
});
|
||||
|
||||
for (coord_t i = 0; i < (coord_t)buckets_area.size() - 1; i = i + 2)
|
||||
@ -1505,9 +1516,9 @@ std::optional<TreeSupport::SupportElement> TreeSupport::increaseSingleArea(AreaI
|
||||
void TreeSupport::increaseAreas(std::unordered_map<SupportElement, Polygons>& to_bp_areas, std::unordered_map<SupportElement, Polygons>& to_model_areas, std::map<SupportElement, Polygons>& influence_areas, std::vector<SupportElement*>& bypass_merge_areas, const std::vector<SupportElement*>& last_layer, const LayerIndex layer_idx, const bool mergelayer)
|
||||
{
|
||||
std::mutex critical_sections;
|
||||
cura::parallel_for<size_t>(0, last_layer.size(), 1,
|
||||
[&](const size_t idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, last_layer.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t idx = range.begin(); idx < range.end(); ++ idx) {
|
||||
SupportElement* parent = last_layer[idx];
|
||||
|
||||
SupportElement elem(parent); // also increases dtt
|
||||
@ -1752,6 +1763,7 @@ void TreeSupport::increaseAreas(std::unordered_map<SupportElement, Polygons>& to
|
||||
{
|
||||
parent->result_on_layer = Point(-1, -1); // If the bottom most point of a branch is set, later functions will assume that the position is valid, and ignore it. But as branches connecting with the model that are to small have to be culled, the bottom most point has to be not set. A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -2052,9 +2064,10 @@ void TreeSupport::generateBranchAreas(std::vector<std::pair<LayerIndex, SupportE
|
||||
const size_t progress_inserts_check_interval = linear_data.size() / progress_report_steps;
|
||||
|
||||
std::mutex critical_sections;
|
||||
cura::parallel_for<size_t>(0, linear_data.size(), 1,
|
||||
[&](const size_t idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, linear_data.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t idx = range.begin(); idx < range.end(); ++ idx) {
|
||||
|
||||
SupportElement* elem = linear_data[idx].second;
|
||||
coord_t radius = config.getRadius(*elem);
|
||||
bool parent_uses_min = false;
|
||||
@ -2165,6 +2178,7 @@ void TreeSupport::generateBranchAreas(std::vector<std::pair<LayerIndex, SupportE
|
||||
Progress::messageProgress(Progress::Stage::SUPPORT, progress_total * progress_multiplier + progress_offset, TREE_PROGRESS_TOTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// single threaded combining all elements to the right layers. ONLY COPYS DATA!
|
||||
@ -2185,9 +2199,10 @@ void TreeSupport::smoothBranchAreas(std::vector<std::unordered_map<SupportElemen
|
||||
std::vector<std::pair<SupportElement*, Polygons>> processing;
|
||||
processing.insert(processing.end(), layer_tree_polygons[layer_idx].begin(), layer_tree_polygons[layer_idx].end());
|
||||
std::vector<std::vector<std::pair<SupportElement*, Polygons>>> update_next(processing.size()); // with this a lock can be avoided
|
||||
cura::parallel_for<size_t>(0, processing.size(), 1,
|
||||
[&](const size_t processing_idx)
|
||||
{
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, processing.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t processing_idx = range.begin(); processing_idx < range.end(); ++ processing_idx) {
|
||||
std::pair<SupportElement*, Polygons> data_pair = processing[processing_idx];
|
||||
|
||||
coord_t max_outer_wall_distance = 0;
|
||||
@ -2212,6 +2227,7 @@ void TreeSupport::smoothBranchAreas(std::vector<std::unordered_map<SupportElemen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (std::vector<std::pair<SupportElement*, Polygons>> data_vector : update_next)
|
||||
@ -2234,9 +2250,9 @@ void TreeSupport::smoothBranchAreas(std::vector<std::unordered_map<SupportElemen
|
||||
processing.insert(processing.end(), layer_tree_polygons[layer_idx].begin(), layer_tree_polygons[layer_idx].end());
|
||||
std::vector<std::pair<SupportElement*, Polygons>> update_next(processing.size(), std::pair<SupportElement*, Polygons>(nullptr, Polygons())); // with this a lock can be avoided
|
||||
|
||||
cura::parallel_for<size_t>(0, processing.size(), 1,
|
||||
[&](const size_t processing_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, processing.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t processing_idx = range.begin(); processing_idx < range.end(); ++ processing_idx) {
|
||||
std::pair<SupportElement*, Polygons> data_pair = processing[processing_idx];
|
||||
bool do_something = false;
|
||||
Polygons max_allowed_area;
|
||||
@ -2266,6 +2282,7 @@ void TreeSupport::smoothBranchAreas(std::vector<std::unordered_map<SupportElemen
|
||||
update_next[processing_idx] = std::pair<SupportElement*, Polygons>(data_pair.first, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updated_last_iteration.clear();
|
||||
@ -2286,9 +2303,9 @@ void TreeSupport::smoothBranchAreas(std::vector<std::unordered_map<SupportElemen
|
||||
|
||||
void TreeSupport::dropNonGraciousAreas(std::vector<std::unordered_map<SupportElement*, Polygons>>& layer_tree_polygons, const std::vector<std::pair<LayerIndex, SupportElement*>>& linear_data, std::vector<std::vector<std::pair<LayerIndex, Polygons>>>& dropped_down_areas, const std::map<SupportElement*, SupportElement*>& inverse_tree_order)
|
||||
{
|
||||
cura::parallel_for<size_t>(0, linear_data.size(), 1,
|
||||
[&](const size_t idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, linear_data.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t idx = range.begin(); idx < range.end(); ++ idx) {
|
||||
SupportElement* elem = linear_data[idx].second;
|
||||
bool non_gracious_model_contact = !elem->to_model_gracious && !inverse_tree_order.count(elem); // if a element has no child, it connects to whatever is below as no support further down for it will exist.
|
||||
|
||||
@ -2303,6 +2320,7 @@ void TreeSupport::dropNonGraciousAreas(std::vector<std::unordered_map<SupportEle
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -2314,9 +2332,9 @@ void TreeSupport::finalizeInterfaceAndSupportAreas(std::vector<Polygons>& suppor
|
||||
|
||||
// Iterate over the generated circles in parallel and clean them up. Also add support floor.
|
||||
std::mutex critical_sections;
|
||||
cura::parallel_for<LayerIndex>(0, static_cast<coord_t>(support_layer_storage.size()), 1,
|
||||
[&](const LayerIndex layer_idx)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, support_layer_storage.size()),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (const size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
support_layer_storage[layer_idx] = support_layer_storage[layer_idx].unionPolygons().smooth(50); // Most of the time in this function is this union call. Can take 300+ ms when a lot of areas are to be unioned.
|
||||
support_layer_storage[layer_idx].simplify(std::min(coord_t(30), config.maximum_resolution), std::min(coord_t(10), config.maximum_deviation)); // simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
|
||||
// Subtract support lines of the branches from the roof
|
||||
@ -2395,6 +2413,7 @@ void TreeSupport::finalizeInterfaceAndSupportAreas(std::vector<Polygons>& suppor
|
||||
storage.support.layer_nr_max_filled_layer = std::max(storage.support.layer_nr_max_filled_layer, static_cast<int>(layer_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user