Cancellation of tree supports

This commit is contained in:
Vojtech Bubnik 2023-01-31 09:12:53 +01:00
parent bd20bd4dc9
commit 2a1e12131b
3 changed files with 149 additions and 81 deletions

View file

@ -222,7 +222,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
#endif // TREE_SUPPORT_SHOW_ERRORS_WIN32
}
[[nodiscard]] static const std::vector<Polygons> generate_overhangs(const PrintObject &print_object)
[[nodiscard]] static const std::vector<Polygons> generate_overhangs(const PrintObject &print_object, std::function<void()> throw_on_cancel)
{
std::vector<Polygons> out(print_object.layer_count(), Polygons{});
@ -241,7 +241,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
auto enforcer_overhang_offset = scaled<double>(config.support_tree_tip_diameter.value);
tbb::parallel_for(tbb::blocked_range<LayerIndex>(1, out.size()),
[&print_object, &enforcers_layers, &blockers_layers, support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &out]
[&print_object, &enforcers_layers, &blockers_layers, support_auto, support_enforce_layers, support_threshold_auto, tan_threshold, enforcer_overhang_offset, &throw_on_cancel, &out]
(const tbb::blocked_range<LayerIndex> &range) {
for (LayerIndex layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
const Layer &current_layer = *print_object.get_layer(layer_id);
@ -307,6 +307,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
}
}
out[layer_id] = std::move(overhangs);
throw_on_cancel();
}
});
@ -319,7 +320,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
* \param storage[in] Background storage to access meshes.
* \param currently_processing_meshes[in] Indexes of all meshes that are processed in this iteration
*/
[[nodiscard]] static LayerIndex precalculate(const Print &print, const std::vector<Polygons> &overhangs, const TreeSupportSettings &config, const std::vector<size_t> &object_ids, TreeModelVolumes &volumes)
[[nodiscard]] static LayerIndex precalculate(const Print &print, const std::vector<Polygons> &overhangs, const TreeSupportSettings &config, const std::vector<size_t> &object_ids, TreeModelVolumes &volumes, std::function<void()> throw_on_cancel)
{
// calculate top most layer that is relevant for support
LayerIndex max_layer = 0;
@ -333,7 +334,7 @@ void tree_supports_show_error(std::string_view message, bool critical)
}
if (max_layer > 0)
// The actual precalculation happens in TreeModelVolumes.
volumes.precalculate(max_layer);
volumes.precalculate(max_layer, throw_on_cancel);
return max_layer;
}
@ -874,7 +875,8 @@ static void generate_initial_areas(
std::vector<SupportElements> &move_bounds,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &top_interface_layers,
SupportGeneratorLayerStorage &layer_storage)
SupportGeneratorLayerStorage &layer_storage,
std::function<void()> throw_on_cancel)
{
using AvoidanceType = TreeModelVolumes::AvoidanceType;
static constexpr const auto base_radius = scaled<int>(0.01);
@ -932,7 +934,7 @@ static void generate_initial_areas(
[&print_object, &volumes, &config, &overhangs, &mesh_config, &mesh_group_settings, &support_params,
z_distance_delta, min_xy_dist, force_tip_to_roof, roof_enabled, support_roof_layers, extra_outset, circle_length_to_half_linewidth_change, connect_length, max_overhang_insert_lag,
&base_circle, &mutex_layer_storage, &mutex_movebounds, &top_contacts, &layer_storage, &already_inserted,
&move_bounds](const tbb::blocked_range<size_t> &range) {
&move_bounds, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
if (overhangs[layer_idx + z_distance_delta].empty())
continue;
@ -1142,6 +1144,8 @@ static void generate_initial_areas(
}
}
throw_on_cancel();
Polygons overhang_roofs;
std::vector<std::pair<ExPolygon, bool>> overhang_processing;
if (roof_enabled) {
@ -1271,6 +1275,7 @@ static void generate_initial_areas(
append(l->polygons, std::move(overhang_outset));
} else // normal trees have to be generated
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);
throw_on_cancel();
}
}
});
@ -1602,7 +1607,8 @@ static void increase_areas_one_layer(
// Layer elements above merging_areas.
SupportElements &layer_elements,
// If false, the merging_areas will not be merged for performance reasons.
const bool mergelayer)
const bool mergelayer,
std::function<void()> throw_on_cancel)
{
using AvoidanceType = TreeModelVolumes::AvoidanceType;
@ -1731,7 +1737,7 @@ static void increase_areas_one_layer(
}
order = new_order;
}
if (elem.to_buildplate || (elem.to_model_gracious && intersection(parent.influence_area, volumes.getPlaceableAreas(radius, layer_idx)).empty())) {
if (elem.to_buildplate || (elem.to_model_gracious && intersection(parent.influence_area, volumes.getPlaceableAreas(radius, layer_idx, throw_on_cancel)).empty())) {
// error case
// it is normal that we wont be able to find a new area at some point in time if we wont be able to reach layer 0 aka have to connect with the model
insertSetting({ AvoidanceType::Fast, fast_speed, !increase_radius, !no_error, elem.use_min_xy_dist, move }, true);
@ -1849,6 +1855,7 @@ static void increase_areas_one_layer(
// A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
parent.state.result_on_layer_reset();
}
throw_on_cancel();
}
});
}
@ -2144,8 +2151,11 @@ static SupportElementMerging* merge_influence_areas_two_sets(
* \param layer_idx[in] The current layer.
*/
static void merge_influence_areas(
const TreeModelVolumes &volumes, const TreeSupportSettings &config, const LayerIndex layer_idx,
std::vector<SupportElementMerging> &influence_areas)
const TreeModelVolumes &volumes,
const TreeSupportSettings &config,
const LayerIndex layer_idx,
std::vector<SupportElementMerging> &influence_areas,
std::function<void()> throw_on_cancel)
{
const size_t input_size = influence_areas.size();
if (input_size == 0)
@ -2164,6 +2174,8 @@ static void merge_influence_areas(
// Sort influence_areas in place.
tree.build_modify_input(influence_areas);
throw_on_cancel();
// Prepare the initial buckets as ranges of influence areas. The initial buckets contain power of 2 influence areas to follow
// the branching of the AABB tree.
// Vectors of ranges of influence areas, following the branching of the AABB tree:
@ -2203,6 +2215,7 @@ static void merge_influence_areas(
const size_t bucket_pair_idx = idx * 2;
// Merge bucket_count adjacent to each other, merging uneven bucket numbers into even buckets
buckets[idx].second = merge_influence_areas_leaves(volumes, config, layer_idx, buckets[idx].first, buckets[idx].second);
throw_on_cancel();
}
});
@ -2217,6 +2230,7 @@ static void merge_influence_areas(
buckets[bucket_pair_idx].second = merge_influence_areas_two_sets(volumes, config, layer_idx,
buckets[bucket_pair_idx].first, buckets[bucket_pair_idx].second,
buckets[bucket_pair_idx + 1].first, buckets[bucket_pair_idx + 1].second);
throw_on_cancel();
}
});
// Remove odd buckets, which were merged into even buckets.
@ -2232,7 +2246,7 @@ static void merge_influence_areas(
*
* \param move_bounds[in,out] All currently existing influence areas
*/
static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupportSettings &config, std::vector<SupportElements> &move_bounds)
static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupportSettings &config, std::vector<SupportElements> &move_bounds, std::function<void()> throw_on_cancel)
{
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
const double data_size_inverse = 1 / double(move_bounds.size());
@ -2269,7 +2283,7 @@ static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupp
parents.emplace_back(element_idx);
influence_areas.push_back({ el.state, parents });
}
increase_areas_one_layer(volumes, config, influence_areas, layer_idx, prev_layer, merge_this_layer);
increase_areas_one_layer(volumes, config, influence_areas, layer_idx, prev_layer, merge_this_layer, throw_on_cancel);
// Place already fully constructed elements to the output, remove them from influence_areas.
SupportElements &this_layer = move_bounds[layer_idx - 1];
@ -2298,7 +2312,7 @@ static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupp
bool reduced_by_merging = false;
if (size_t count_before_merge = influence_areas.size(); count_before_merge > 1) {
// ### Calculate which influence areas overlap, and merge them into a new influence area (simplified: an intersection of influence areas that have such an intersection)
merge_influence_areas(volumes, config, layer_idx, influence_areas);
merge_influence_areas(volumes, config, layer_idx, influence_areas, throw_on_cancel);
reduced_by_merging = count_before_merge > influence_areas.size();
}
last_merge_layer_idx = layer_idx;
@ -2323,6 +2337,7 @@ static void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupp
progress_total += data_size_inverse * TREE_PROGRESS_AREA_CALC;
Progress::messageProgress(Progress::Stage::SUPPORT, progress_total * m_progress_multiplier + m_progress_offset, TREE_PROGRESS_TOTAL);
#endif
throw_on_cancel();
}
BOOST_LOG_TRIVIAL(info) << "Time spent with creating influence areas' subtasks: Increasing areas " << dur_inc.count() / 1000000 <<
@ -2382,7 +2397,8 @@ static void set_to_model_contact_to_model_gracious(
const TreeModelVolumes &volumes,
const TreeSupportSettings &config,
std::vector<SupportElements> &move_bounds,
SupportElement &first_elem)
SupportElement &first_elem,
std::function<void()> throw_on_cancel)
{
SupportElement *last_successfull_layer = nullptr;
@ -2390,7 +2406,7 @@ static void set_to_model_contact_to_model_gracious(
{
SupportElement *elem = &first_elem;
for (LayerIndex layer_check = elem->state.layer_idx;
! intersection(elem->influence_area, volumes.getPlaceableAreas(config.getCollisionRadius(elem->state), layer_check)).empty();
! intersection(elem->influence_area, volumes.getPlaceableAreas(config.getCollisionRadius(elem->state), layer_check, throw_on_cancel)).empty();
elem = &move_bounds[++ layer_check][elem->parents.front()]) {
assert(elem->state.layer_idx == layer_check);
assert(! elem->state.deleted);
@ -2475,7 +2491,8 @@ static void remove_deleted_elements(std::vector<SupportElements> &move_bounds)
static void create_nodes_from_area(
const TreeModelVolumes &volumes,
const TreeSupportSettings &config,
std::vector<SupportElements> &move_bounds)
std::vector<SupportElements> &move_bounds,
std::function<void()> throw_on_cancel)
{
// Initialize points on layer 0, with a "random" point in the influence area.
// Point is chosen based on an inaccurate estimate where the branches will split into two, but every point inside the influence area would produce a valid result.
@ -2490,6 +2507,8 @@ static void create_nodes_from_area(
}
}
throw_on_cancel();
for (LayerIndex layer_idx = 1; layer_idx < LayerIndex(move_bounds.size()); ++ layer_idx) {
auto &layer = move_bounds[layer_idx];
auto *layer_above = layer_idx + 1 < move_bounds.size() ? &move_bounds[layer_idx + 1] : nullptr;
@ -2512,7 +2531,7 @@ static void create_nodes_from_area(
} else {
// set the point where the branch will be placed on the model
if (elem.state.to_model_gracious)
set_to_model_contact_to_model_gracious(volumes, config, move_bounds, elem);
set_to_model_contact_to_model_gracious(volumes, config, move_bounds, elem, throw_on_cancel);
else
set_to_model_contact_simple(elem);
}
@ -2531,6 +2550,7 @@ static void create_nodes_from_area(
set_points_on_areas(elem, layer_above);
}
}
throw_on_cancel();
}
#ifndef NDEBUG
@ -2601,7 +2621,12 @@ struct DrawArea
* \param layer_tree_polygons[out] Resulting branch areas with the layerindex they appear on. layer_tree_polygons.size() has to be at least linear_data.size() as each Influence area in linear_data will save have at least one (that's why it's a vector<vector>) corresponding branch area in layer_tree_polygons.
* \param inverse_tree_order[in] A mapping that returns the child of every influence area.
*/
static void generate_branch_areas(const TreeModelVolumes &volumes, const TreeSupportSettings &config, const std::vector<SupportElements> &move_bounds, std::vector<DrawArea> &linear_data)
static void generate_branch_areas(
const TreeModelVolumes &volumes,
const TreeSupportSettings &config,
const std::vector<SupportElements> &move_bounds,
std::vector<DrawArea> &linear_data,
std::function<void()> throw_on_cancel)
{
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
double progress_total = TREE_PROGRESS_PRECALC_AVO + TREE_PROGRESS_PRECALC_COLL + TREE_PROGRESS_GENERATE_NODES + TREE_PROGRESS_AREA_CALC;
@ -2614,7 +2639,7 @@ static void generate_branch_areas(const TreeModelVolumes &volumes, const TreeSup
const Polygon branch_circle = make_circle(config.branch_radius, SUPPORT_TREE_CIRCLE_RESOLUTION);
tbb::parallel_for(tbb::blocked_range<size_t>(0, linear_data.size()),
[&volumes, &config, &move_bounds, &linear_data, &branch_circle](const tbb::blocked_range<size_t> &range) {
[&volumes, &config, &move_bounds, &linear_data, &branch_circle, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
for (size_t idx = range.begin(); idx < range.end(); ++ idx) {
DrawArea &draw_area = linear_data[idx];
const LayerIndex layer_idx = draw_area.element->state.layer_idx;
@ -2717,6 +2742,7 @@ static void generate_branch_areas(const TreeModelVolumes &volumes, const TreeSup
Progress::messageProgress(Progress::Stage::SUPPORT, progress_total * m_progress_multiplier + m_progress_offset, TREE_PROGRESS_TOTAL);
}
#endif
throw_on_cancel();
}
});
}
@ -2730,7 +2756,8 @@ static void smooth_branch_areas(
const TreeSupportSettings &config,
std::vector<SupportElements> &move_bounds,
std::vector<DrawArea> &linear_data,
const std::vector<size_t> &linear_data_layers)
const std::vector<size_t> &linear_data_layers,
std::function<void()> throw_on_cancel)
{
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
double progress_total = TREE_PROGRESS_PRECALC_AVO + TREE_PROGRESS_PRECALC_COLL + TREE_PROGRESS_GENERATE_NODES + TREE_PROGRESS_AREA_CALC + TREE_PROGRESS_GENERATE_BRANCH_AREAS;
@ -2792,6 +2819,7 @@ static void smooth_branch_areas(
}
}
}
throw_on_cancel();
}
});
}
@ -2835,6 +2863,7 @@ static void smooth_branch_areas(
draw_area.polygons = std::move(result);
}
}
throw_on_cancel();
}
});
}
@ -2856,12 +2885,13 @@ static void smooth_branch_areas(
static void drop_non_gracious_areas(
const TreeModelVolumes &volumes,
const std::vector<DrawArea> &linear_data,
std::vector<Polygons> &support_layer_storage)
std::vector<Polygons> &support_layer_storage,
std::function<void()> throw_on_cancel)
{
std::vector<std::vector<std::pair<LayerIndex, Polygons>>> dropped_down_areas(linear_data.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, linear_data.size()),
[&](const tbb::blocked_range<size_t> &range) {
for (size_t idx = range.begin(); idx < range.end(); ++ idx)
for (size_t idx = range.begin(); idx < range.end(); ++ idx) {
// If a element has no child, it connects to whatever is below as no support further down for it will exist.
if (const DrawArea &draw_element = linear_data[idx]; ! draw_element.element->state.to_model_gracious && draw_element.child_element == nullptr) {
Polygons rest_support;
@ -2871,6 +2901,8 @@ static void drop_non_gracious_areas(
dropped_down_areas[idx].emplace_back(layer_idx, rest_support);
}
}
throw_on_cancel();
}
});
for (coord_t i = 0; i < static_cast<coord_t>(dropped_down_areas.size()); i++)
@ -2896,7 +2928,9 @@ static void finalize_interface_and_support_areas(
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage)
SupportGeneratorLayerStorage &layer_storage,
std::function<void()> throw_on_cancel)
{
InterfacePreference interface_pref = config.interface_preference; // InterfacePreference::SupportLinesOverwriteInterface;
@ -3013,6 +3047,7 @@ static void finalize_interface_and_support_areas(
storage.support.layer_nr_max_filled_layer = std::max(storage.support.layer_nr_max_filled_layer, static_cast<int>(layer_idx));
}
#endif
throw_on_cancel();
}
});
}
@ -3033,7 +3068,8 @@ static void draw_areas(
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage)
SupportGeneratorLayerStorage &layer_storage,
std::function<void()> throw_on_cancel)
{
std::vector<Polygons> support_layer_storage(move_bounds.size());
std::vector<Polygons> support_roof_storage(move_bounds.size());
@ -3071,6 +3107,8 @@ static void draw_areas(
linear_data_layers.emplace_back(linear_data.size());
}
throw_on_cancel();
#ifndef NDEBUG
for (size_t i = 0; i < move_bounds.size(); ++ i) {
size_t begin = linear_data_layers[i];
@ -3082,7 +3120,7 @@ static void draw_areas(
auto t_start = std::chrono::high_resolution_clock::now();
// Generate the circles that will be the branches.
generate_branch_areas(volumes, config, move_bounds, linear_data);
generate_branch_areas(volumes, config, move_bounds, linear_data, throw_on_cancel);
#if 0
assert(linear_data_layers.size() == move_bounds.size() + 1);
@ -3115,7 +3153,7 @@ static void draw_areas(
auto t_generate = std::chrono::high_resolution_clock::now();
// In some edgecases a branch may go though a hole, where the regular radius does not fit. This can result in an apparent jump in branch radius. As such this cases need to be caught and smoothed out.
smooth_branch_areas(config, move_bounds, linear_data, linear_data_layers);
smooth_branch_areas(config, move_bounds, linear_data, linear_data_layers, throw_on_cancel);
#if 0
for (size_t area_layer_idx = 0; area_layer_idx + 1 < linear_data_layers.size(); ++area_layer_idx) {
@ -3133,7 +3171,7 @@ static void draw_areas(
auto t_smooth = std::chrono::high_resolution_clock::now();
// drop down all trees that connect non gracefully with the model
drop_non_gracious_areas(volumes, linear_data, support_layer_storage);
drop_non_gracious_areas(volumes, linear_data, support_layer_storage, throw_on_cancel);
auto t_drop = std::chrono::high_resolution_clock::now();
// Single threaded combining all support areas to the right layers.
@ -3156,7 +3194,7 @@ static void draw_areas(
}
finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
auto t_end = std::chrono::high_resolution_clock::now();
auto dur_gen_tips = 0.001 * std::chrono::duration_cast<std::chrono::microseconds>(t_generate - t_start).count();
@ -3403,7 +3441,8 @@ static void organic_smooth_branches_avoid_collisions(
const TreeSupportSettings &config,
std::vector<SupportElements> &move_bounds,
const std::vector<std::pair<SupportElement*, int>> &elements_with_link_down,
const std::vector<size_t> &linear_data_layers)
const std::vector<size_t> &linear_data_layers,
std::function<void()> throw_on_cancel)
{
struct LayerCollisionCache {
coord_t min_element_radius{ std::numeric_limits<coord_t>::max() };
@ -3426,6 +3465,9 @@ static void organic_smooth_branches_avoid_collisions(
auto& l = layer_collision_cache[layer_idx];
l.min_element_radius = std::min(l.min_element_radius, config.getRadius(element.first->state));
}
throw_on_cancel();
for (LayerIndex layer_idx = 0; layer_idx < LayerIndex(layer_collision_cache.size()); ++layer_idx)
if (LayerCollisionCache& l = layer_collision_cache[layer_idx]; !l.min_element_radius_known())
l.min_element_radius = 0;
@ -3440,6 +3482,7 @@ static void organic_smooth_branches_avoid_collisions(
for (const Line &line : alines)
l.lines.push_back({ unscaled<double>(line.a), unscaled<double>(line.b) });
l.aabbtree_lines = AABBTreeLines::build_aabb_tree_over_indexed_lines(l.lines);
throw_on_cancel();
}
struct CollisionSphere {
@ -3511,6 +3554,8 @@ static void organic_smooth_branches_avoid_collisions(
collision_sphere.layer_end = std::max(collision_sphere.element.state.layer_idx, layer_idx_floor(slicing_params, collision_sphere.max_z)) + 1;
}
throw_on_cancel();
static constexpr const double collision_extra_gap = 0.1;
static constexpr const double max_nudge_collision_avoidance = 0.2;
static constexpr const double max_nudge_smoothing = 0.2;
@ -3521,7 +3566,7 @@ static void organic_smooth_branches_avoid_collisions(
collision_sphere.prev_position = collision_sphere.position;
std::atomic<size_t> num_moved{ 0 };
tbb::parallel_for(tbb::blocked_range<size_t>(0, collision_spheres.size()),
[&collision_spheres, &layer_collision_cache, &slicing_params, &move_bounds, &linear_data_layers, &num_moved](const tbb::blocked_range<size_t> range) {
[&collision_spheres, &layer_collision_cache, &slicing_params, &move_bounds, &linear_data_layers, &num_moved, &throw_on_cancel](const tbb::blocked_range<size_t> range) {
for (size_t collision_sphere_id = range.begin(); collision_sphere_id < range.end(); ++ collision_sphere_id)
if (CollisionSphere &collision_sphere = collision_spheres[collision_sphere_id]; ! collision_sphere.locked) {
// Calculate collision of multiple 2D layers against a collision sphere.
@ -3579,6 +3624,8 @@ static void organic_smooth_branches_avoid_collisions(
// Shift by maximum 1mm, less than the collision avoidance factor.
double nudge_dist = std::min(std::max(0., nudge_dist_max), max_nudge_smoothing);
collision_sphere.position.head<2>() += (shift.normalized() * nudge_dist).cast<float>();
throw_on_cancel();
}
});
// printf("iteration: %d, moved: %d\n", int(iter), int(num_moved));
@ -3703,7 +3750,9 @@ static void draw_branches(
SupportGeneratorLayersPtr &bottom_contacts,
SupportGeneratorLayersPtr &top_contacts,
SupportGeneratorLayersPtr &intermediate_layers,
SupportGeneratorLayerStorage &layer_storage)
SupportGeneratorLayerStorage &layer_storage,
std::function<void()> throw_on_cancel)
{
static int irun = 0;
@ -3745,7 +3794,9 @@ static void draw_branches(
}
}
organic_smooth_branches_avoid_collisions(print_object, volumes, config, move_bounds, elements_with_link_down, linear_data_layers);
throw_on_cancel();
organic_smooth_branches_avoid_collisions(print_object, volumes, config, move_bounds, elements_with_link_down, linear_data_layers, throw_on_cancel);
std::vector<Polygons> support_layer_storage(move_bounds.size());
std::vector<Polygons> support_roof_storage(move_bounds.size());
@ -3812,6 +3863,7 @@ static void draw_branches(
#endif
its_merge(cummulative_mesh, partial_mesh);
}
throw_on_cancel();
}
}
@ -3855,7 +3907,7 @@ static void draw_branches(
});
finalize_interface_and_support_areas(print_object, volumes, config, overhangs, support_layer_storage, support_roof_storage,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
}
/*!
@ -3916,10 +3968,10 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume
//FIXME generating overhangs just for the furst mesh of the group.
assert(processing.second.size() == 1);
std::vector<Polygons> overhangs = generate_overhangs(*print.get_object(processing.second.front()));
std::vector<Polygons> overhangs = generate_overhangs(*print.get_object(processing.second.front()), throw_on_cancel);
// ### Precalculate avoidances, collision etc.
size_t num_support_layers = precalculate(print, overhangs, processing.first, processing.second, volumes);
size_t num_support_layers = precalculate(print, overhangs, processing.first, processing.second, volumes, throw_on_cancel);
if (num_support_layers == 0)
continue;
@ -3936,7 +3988,7 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume
SupportGeneratorLayerStorage layer_storage;
for (size_t mesh_idx : processing.second)
generate_initial_areas(*print.get_object(mesh_idx), volumes, config, overhangs, move_bounds, top_contacts, top_interface_layers, layer_storage);
generate_initial_areas(*print.get_object(mesh_idx), volumes, config, overhangs, move_bounds, top_contacts, top_interface_layers, layer_storage, throw_on_cancel);
auto t_gen = std::chrono::high_resolution_clock::now();
#ifdef TREESUPPORT_DEBUG_SVG
@ -3953,22 +4005,22 @@ static void generate_support_areas(Print &print, const BuildVolume &build_volume
#endif // TREESUPPORT_DEBUG_SVG
// ### Propagate the influence areas downwards. This is an inherently serial operation.
create_layer_pathing(volumes, config, move_bounds);
create_layer_pathing(volumes, config, move_bounds, throw_on_cancel);
auto t_path = std::chrono::high_resolution_clock::now();
// ### Set a point in each influence area
create_nodes_from_area(volumes, config, move_bounds);
create_nodes_from_area(volumes, config, move_bounds, throw_on_cancel);
auto t_place = std::chrono::high_resolution_clock::now();
// ### draw these points as circles
if (print_object.config().support_material_style == smsTree)
draw_areas(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
else {
assert(print_object.config().support_material_style == smsOrganic);
draw_branches(*print.get_object(processing.second.front()), volumes, config, overhangs, move_bounds,
bottom_contacts, top_contacts, intermediate_layers, layer_storage);
bottom_contacts, top_contacts, intermediate_layers, layer_storage, throw_on_cancel);
}
auto t_draw = std::chrono::high_resolution_clock::now();