From c838fc92fc1ebb19791e003dd4481f21d5ee12c8 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 8 May 2023 10:25:28 +0200 Subject: [PATCH] Follow-up to 1e7a3216ca87d9fdeaa5b12f813e5900a77d49bc WIP Organic supports intefaces: bugfixes --- src/libslic3r/Support/SupportCommon.cpp | 37 +++++++++++++------------ src/libslic3r/Support/TreeSupport.cpp | 13 +++++++-- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/Support/SupportCommon.cpp b/src/libslic3r/Support/SupportCommon.cpp index 4978b9e40..951ae740d 100644 --- a/src/libslic3r/Support/SupportCommon.cpp +++ b/src/libslic3r/Support/SupportCommon.cpp @@ -137,7 +137,8 @@ std::pair generate_interfa if (! intermediate_layers.empty() && support_params.has_interfaces()) { // For all intermediate layers, collect top contact surfaces, which are not further than support_material_interface_layers. BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - start"; - const bool snug_supports = config.support_material_style.value != smsGrid; + const bool snug_supports = config.support_material_style.value == smsSnug; + const bool smooth_supports = config.support_material_style.value != smsGrid; SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first; SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second; interface_layers.assign(intermediate_layers.size(), nullptr); @@ -147,7 +148,7 @@ std::pair generate_interfa const auto minimum_island_radius = support_params.support_material_interface_flow.scaled_spacing() / support_params.interface_density; const auto closing_distance = smoothing_distance; // scaled(config.support_material_closing_radius.value); // Insert a new layer into base_interface_layers, if intersection with base exists. - auto insert_layer = [&layer_storage, snug_supports, closing_distance, smoothing_distance, minimum_island_radius]( + auto insert_layer = [&layer_storage, smooth_supports, closing_distance, smoothing_distance, minimum_island_radius]( SupportGeneratorLayer &intermediate_layer, Polygons &bottom, Polygons &&top, SupportGeneratorLayer *top_interface_layer, const Polygons *subtract, SupporLayerType type) -> SupportGeneratorLayer* { bool has_top_interface = top_interface_layer && ! top_interface_layer->polygons.empty(); @@ -156,14 +157,16 @@ std::pair generate_interfa append(bottom, std::move(top)); // Merge top / bottom interfaces. For snug supports, merge using closing distance and regularize (close concave corners). bottom = intersection( - snug_supports ? + smooth_supports ? smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) : union_safety_offset(std::move(bottom)), intermediate_layer.polygons); - if (has_top_interface) + if (has_top_interface) { // Don't trim the precomputed Organic supports top interface with base layer // as the precomputed top interface likely expands over multiple tree tips. bottom = union_(std::move(top_interface_layer->polygons), bottom); + top_interface_layer->polygons.clear(); + } if (! bottom.empty()) { //FIXME Remove non-printable tiny islands, let them be printed using the base support. //bottom = opening(std::move(bottom), minimum_island_radius); @@ -253,13 +256,8 @@ std::pair generate_interfa auto resolve_same_layer = [](SupportGeneratorLayersPtr &layers, int &idx, coordf_t print_z) -> SupportGeneratorLayer* { if (! layers.empty()) { idx = idx_higher_or_equal(layers, idx, [print_z](const SupportGeneratorLayer *layer) { return layer->print_z > print_z - EPSILON; }); - if (idx < int(layers.size()) && layers[idx]->print_z < print_z + EPSILON) { - SupportGeneratorLayer *l = layers[idx]; - // Remove the layer from the source container, as it will be consumed here: It will be merged - // with the newly produced interfaces. - layers[idx] = nullptr; - return l; - } + if (idx < int(layers.size()) && layers[idx]->print_z < print_z + EPSILON) + return layers[idx]; } return nullptr; }; @@ -284,11 +282,14 @@ std::pair generate_interfa // Compress contact_out, remove the nullptr items. // The parallel_for above may not have merged all the interface and base_interface layers // generated by the Organic supports code, do it here. - auto merge_remove_nulls = [](SupportGeneratorLayersPtr &in1, SupportGeneratorLayersPtr &in2) { - size_t nonzeros = std::count_if(in1.begin(), in1.end(), [](auto *l) { return l != nullptr; }) + - std::count_if(in2.begin(), in2.end(), [](auto *l) { return l != nullptr; }); - remove_nulls(in1); - remove_nulls(in2); + auto merge_remove_empty = [](SupportGeneratorLayersPtr &in1, SupportGeneratorLayersPtr &in2) { + auto remove_empty = [](SupportGeneratorLayersPtr &vec) { + vec.erase( + std::remove_if(vec.begin(), vec.end(), [](const SupportGeneratorLayer *ptr) { return ptr == nullptr || ptr->polygons.empty(); }), + vec.end()); + }; + remove_empty(in1); + remove_empty(in2); if (in2.empty()) return std::move(in1); else if (in1.empty()) @@ -299,8 +300,8 @@ std::pair generate_interfa return std::move(out); } }; - interface_layers = merge_remove_nulls(interface_layers, top_interface_layers); - base_interface_layers = merge_remove_nulls(base_interface_layers, top_base_interface_layers); + interface_layers = merge_remove_empty(interface_layers, top_interface_layers); + base_interface_layers = merge_remove_empty(base_interface_layers, top_base_interface_layers); BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_interface_layers() in parallel - end"; } diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index dfeb3fdf9..e27661384 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -1119,7 +1119,7 @@ public: void add_roof_build_plate(Polygons &&overhang_areas, size_t dtt_roof) { std::lock_guard lock(m_mutex_layer_storage); - this->add_roof_unguarded(std::move(overhang_areas), 0, dtt_roof); + this->add_roof_unguarded(std::move(overhang_areas), 0, std::min(dtt_roof, this->support_parameters.num_top_interface_layers)); } // called by sample_overhang_area() @@ -1204,6 +1204,8 @@ public: private: void add_roof_unguarded(Polygons &&new_roofs, const size_t insert_layer_idx, const size_t dtt_roof) { + assert(support_parameters.has_top_contacts); + assert(dtt_roof <= support_parameters.num_top_interface_layers); SupportGeneratorLayersPtr &layers = dtt_roof == 0 ? this->top_contacts : dtt_roof <= support_parameters.num_top_interface_layers_only() ? this->top_interfaces : this->top_base_interfaces; @@ -4413,8 +4415,13 @@ static void draw_branches( bottom_extra_slices.back().polygons, volumes.getPlaceableAreas(0, layer_begin - LayerIndex(bottom_extra_slices.size()), [] {})); if (area(this_bottom_contacts) < support_area_min) bottom_extra_slices.pop_back(); - else if (config.settings.support_floor_layers > 0) - bottom_contacts.emplace_back(std::move(this_bottom_contacts)); + else { + // At least a fraction of the tree bottom is considered to be supported. + if (config.settings.support_floor_layers > 0) + // Turn this fraction of the tree bottom into a contact layer. + bottom_contacts.emplace_back(std::move(this_bottom_contacts)); + break; + } } if (config.settings.support_floor_layers > 0) for (int i = int(bottom_extra_slices.size()) - 2; i >= 0; -- i)