From f3fddcb225d02abc7696050cafe3428a7f1878bd Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Wed, 22 Jan 2025 10:01:15 +0800 Subject: [PATCH] Fix issue that support surfaces get filtered out unexpectly (#7988) Fix issue that support surfaces get filtered out unexpectly (SoftFever/OrcaSlicer#7935) --- src/libslic3r/Support/SupportMaterial.cpp | 474 ++++++++-------------- src/libslic3r/Support/SupportMaterial.hpp | 170 ++------ 2 files changed, 204 insertions(+), 440 deletions(-) diff --git a/src/libslic3r/Support/SupportMaterial.cpp b/src/libslic3r/Support/SupportMaterial.cpp index 46dd1d8ac9..4d0aafcffb 100644 --- a/src/libslic3r/Support/SupportMaterial.cpp +++ b/src/libslic3r/Support/SupportMaterial.cpp @@ -4,7 +4,7 @@ #include "Layer.hpp" #include "Print.hpp" #include "SupportMaterial.hpp" -#include "Fill/FillBase.hpp" +#include "SupportCommon.hpp" #include "Geometry.hpp" #include "Point.hpp" #include "MutablePolygon.hpp" @@ -70,17 +70,17 @@ namespace Slic3r { static constexpr bool support_with_sheath = false; #ifdef SLIC3R_DEBUG -const char* support_surface_type_to_color_name(const PrintObjectSupportMaterial::SupporLayerType surface_type) +const char* support_surface_type_to_color_name(const SupporLayerType surface_type) { switch (surface_type) { - case PrintObjectSupportMaterial::sltTopContact: return "rgb(255,0,0)"; // "red"; - case PrintObjectSupportMaterial::sltTopInterface: return "rgb(0,255,0)"; // "green"; - case PrintObjectSupportMaterial::sltBase: return "rgb(0,0,255)"; // "blue"; - case PrintObjectSupportMaterial::sltBottomInterface:return "rgb(255,255,128)"; // yellow - case PrintObjectSupportMaterial::sltBottomContact: return "rgb(255,0,255)"; // magenta - case PrintObjectSupportMaterial::sltRaftInterface: return "rgb(0,255,255)"; - case PrintObjectSupportMaterial::sltRaftBase: return "rgb(128,128,128)"; - case PrintObjectSupportMaterial::sltUnknown: return "rgb(128,0,0)"; // maroon + case SupporLayerType::TopContact: return "rgb(255,0,0)"; // "red"; + case SupporLayerType::TopInterface: return "rgb(0,255,0)"; // "green"; + case SupporLayerType::Base: return "rgb(0,0,255)"; // "blue"; + case SupporLayerType::BottomInterface:return "rgb(255,255,128)"; // yellow + case SupporLayerType::BottomContact: return "rgb(255,0,255)"; // magenta + case SupporLayerType::RaftInterface: return "rgb(0,255,255)"; + case SupporLayerType::RaftBase: return "rgb(128,128,128)"; + case SupporLayerType::Unknown: return "rgb(128,0,0)"; // maroon default: return "rgb(64,64,64)"; }; } @@ -97,28 +97,28 @@ void export_support_surface_type_legend_to_svg(SVG &svg, const Point &pos) coord_t pos_x = pos_x0; coord_t pos_y = pos(1) + scale_(1.5); coord_t step_x = scale_(10.); - svg.draw_legend(Point(pos_x, pos_y), "top contact" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltTopContact)); + svg.draw_legend(Point(pos_x, pos_y), "top contact" , support_surface_type_to_color_name(SupporLayerType::TopContact)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "top iface" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltTopInterface)); + svg.draw_legend(Point(pos_x, pos_y), "top iface" , support_surface_type_to_color_name(SupporLayerType::TopInterface)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "base" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltBase)); + svg.draw_legend(Point(pos_x, pos_y), "base" , support_surface_type_to_color_name(SupporLayerType::Base)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "bottom iface" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltBottomInterface)); + svg.draw_legend(Point(pos_x, pos_y), "bottom iface" , support_surface_type_to_color_name(SupporLayerType::BottomInterface)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "bottom contact" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltBottomContact)); + svg.draw_legend(Point(pos_x, pos_y), "bottom contact" , support_surface_type_to_color_name(SupporLayerType::BottomContact)); // 2nd row pos_x = pos_x0; pos_y = pos(1)+scale_(2.8); - svg.draw_legend(Point(pos_x, pos_y), "raft interface" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltRaftInterface)); + svg.draw_legend(Point(pos_x, pos_y), "raft interface" , support_surface_type_to_color_name(SupporLayerType::RaftInterface)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "raft base" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltRaftBase)); + svg.draw_legend(Point(pos_x, pos_y), "raft base" , support_surface_type_to_color_name(SupporLayerType::RaftBase)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "unknown" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltUnknown)); + svg.draw_legend(Point(pos_x, pos_y), "unknown" , support_surface_type_to_color_name(SupporLayerType::Unknown)); pos_x += step_x; - svg.draw_legend(Point(pos_x, pos_y), "intermediate" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltIntermediate)); + svg.draw_legend(Point(pos_x, pos_y), "intermediate" , support_surface_type_to_color_name(SupporLayerType::Intermediate)); } -void export_print_z_polygons_to_svg(const char *path, PrintObjectSupportMaterial::MyLayer ** const layers, size_t n_layers) +void export_print_z_polygons_to_svg(const char *path, SupportGeneratorLayer ** const layers, size_t n_layers) { BoundingBox bbox; for (int i = 0; i < n_layers; ++ i) @@ -138,7 +138,7 @@ void export_print_z_polygons_to_svg(const char *path, PrintObjectSupportMaterial void export_print_z_polygons_and_extrusions_to_svg( const char *path, - PrintObjectSupportMaterial::MyLayer ** const layers, + SupportGeneratorLayer ** const layers, size_t n_layers, SupportLayer &support_layer) { @@ -426,36 +426,36 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object } // Using the std::deque as an allocator. -inline PrintObjectSupportMaterial::MyLayer& layer_allocate( - std::deque &layer_storage, - PrintObjectSupportMaterial::SupporLayerType layer_type) +inline SupportGeneratorLayer& layer_allocate( + std::deque &layer_storage, + SupporLayerType layer_type) { - layer_storage.push_back(PrintObjectSupportMaterial::MyLayer()); + layer_storage.push_back(SupportGeneratorLayer()); layer_storage.back().layer_type = layer_type; return layer_storage.back(); } -inline PrintObjectSupportMaterial::MyLayer& layer_allocate( - std::deque &layer_storage, +inline SupportGeneratorLayer& layer_allocate( + std::deque &layer_storage, tbb::spin_mutex &layer_storage_mutex, - PrintObjectSupportMaterial::SupporLayerType layer_type) + SupporLayerType layer_type) { layer_storage_mutex.lock(); - layer_storage.push_back(PrintObjectSupportMaterial::MyLayer()); - PrintObjectSupportMaterial::MyLayer *layer_new = &layer_storage.back(); + layer_storage.push_back(SupportGeneratorLayer()); + SupportGeneratorLayer *layer_new = &layer_storage.back(); layer_storage_mutex.unlock(); layer_new->layer_type = layer_type; return *layer_new; } -inline void layers_append(PrintObjectSupportMaterial::MyLayersPtr &dst, const PrintObjectSupportMaterial::MyLayersPtr &src) +inline void layers_append(SupportGeneratorLayersPtr &dst, const SupportGeneratorLayersPtr &src) { dst.insert(dst.end(), src.begin(), src.end()); } // Support layer that is covered by some form of dense interface. -static constexpr const std::initializer_list support_types_interface { - PrintObjectSupportMaterial::sltRaftInterface, PrintObjectSupportMaterial::sltBottomContact, PrintObjectSupportMaterial::sltBottomInterface, PrintObjectSupportMaterial::sltTopContact, PrintObjectSupportMaterial::sltTopInterface +static constexpr const std::initializer_list support_types_interface { + SupporLayerType::RaftInterface, SupporLayerType::BottomContact, SupporLayerType::BottomInterface, SupporLayerType::TopContact, SupporLayerType::TopInterface }; void PrintObjectSupportMaterial::generate(PrintObject &object) @@ -468,7 +468,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // Layer instances will be allocated by std::deque and they will be kept until the end of this function call. // The layers will be referenced by various LayersPtr (of type std::vector) - MyLayerStorage layer_storage; + SupportGeneratorLayerStorage layer_storage; BOOST_LOG_TRIVIAL(info) << "Support generator - Creating top contacts"; @@ -481,7 +481,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // should the support material expose to the object in order to guarantee // that it will be effective, regardless of how it's built below. // If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette without holes. - MyLayersPtr top_contacts = this->top_contact_layers(object, buildplate_covered, layer_storage); + SupportGeneratorLayersPtr top_contacts = this->top_contact_layers(object, buildplate_covered, layer_storage); if (top_contacts.empty()) // Nothing is supported, no supports are generated. return; @@ -492,7 +492,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) #ifdef SLIC3R_DEBUG static int iRun = 0; iRun ++; - for (const MyLayer *layer : top_contacts) + for (const SupportGeneratorLayer *layer : top_contacts) Slic3r::SVG::export_expolygons( debug_out_path("support-top-contacts-%d-%lf.svg", iRun, layer->print_z), union_ex(layer->polygons)); @@ -505,7 +505,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // layer_support_areas contains the per object layer support areas. These per object layer support areas // may get merged and trimmed by this->generate_base_layers() if the support layers are not synchronized with object layers. std::vector layer_support_areas; - MyLayersPtr bottom_contacts = this->bottom_contact_layers_and_layer_support_areas( + SupportGeneratorLayersPtr bottom_contacts = this->bottom_contact_layers_and_layer_support_areas( object, top_contacts, buildplate_covered, layer_storage, layer_support_areas); @@ -526,13 +526,13 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // The layers may or may not be synchronized with the object layers, depending on the configuration. // For example, a single nozzle multi material printing will need to generate a waste tower, which in turn // wastes less material, if there are as little tool changes as possible. - MyLayersPtr intermediate_layers = this->raft_and_intermediate_support_layers( + SupportGeneratorLayersPtr intermediate_layers = this->raft_and_intermediate_support_layers( object, bottom_contacts, top_contacts, layer_storage); this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.gap_support_object, m_slicing_params.gap_object_support, m_support_params.gap_xy); #ifdef SLIC3R_DEBUG - for (const MyLayer *layer : top_contacts) + for (const SupportGeneratorLayer *layer : top_contacts) Slic3r::SVG::export_expolygons( debug_out_path("support-top-contacts-trimmed-by-object-%d-%lf.svg", iRun, layer->print_z), union_ex(layer->polygons)); @@ -544,7 +544,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) this->generate_base_layers(object, bottom_contacts, top_contacts, intermediate_layers, layer_support_areas); #ifdef SLIC3R_DEBUG - for (MyLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++ it) + for (SupportGeneratorLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++ it) Slic3r::SVG::export_expolygons( debug_out_path("support-base-layers-%d-%lf.svg", iRun, (*it)->print_z), union_ex((*it)->polygons)); @@ -570,17 +570,17 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // If raft is to be generated, the 1st top_contact layer will contain the 1st object layer silhouette with holes filled. // There is also a 1st intermediate layer containing bases of support columns. // Inflate the bases of the support columns and create the raft base under the object. - MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, base_interface_layers, intermediate_layers, layer_storage); + SupportGeneratorLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, interface_layers, base_interface_layers, intermediate_layers, layer_storage); if (object.print()->canceled()) return; #ifdef SLIC3R_DEBUG - for (const MyLayer *l : interface_layers) + for (const SupportGeneratorLayer *l : interface_layers) Slic3r::SVG::export_expolygons( debug_out_path("support-interface-layers-%d-%lf.svg", iRun, l->print_z), union_ex(l->polygons)); - for (const MyLayer *l : base_interface_layers) + for (const SupportGeneratorLayer *l : base_interface_layers) Slic3r::SVG::export_expolygons( debug_out_path("support-base-interface-layers-%d-%lf.svg", iRun, l->print_z), union_ex(l->polygons)); @@ -603,94 +603,10 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) // intermediate_layers.clear(); // interface_layers.clear(); - // Install support layers into the object. - // A support layer installed on a PrintObject has a unique print_z. - MyLayersPtr layers_sorted; - layers_sorted.reserve(raft_layers.size() + bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size() + base_interface_layers.size()); - layers_append(layers_sorted, raft_layers); - layers_append(layers_sorted, bottom_contacts); - layers_append(layers_sorted, top_contacts); - layers_append(layers_sorted, intermediate_layers); - layers_append(layers_sorted, interface_layers); - layers_append(layers_sorted, base_interface_layers); - // Sort the layers lexicographically by a raising print_z and a decreasing height. - std::sort(layers_sorted.begin(), layers_sorted.end(), [](auto *l1, auto *l2) { return *l1 < *l2; }); - - // BBS: MusangKing - erase mini layer heights (< 0.08mm) arised by top/bottom_z_distance & top_contacts under variable layer height - if (this->synchronize_layers() && !object.slicing_parameters().soluble_interface) { - auto thres = m_support_params.support_layer_height_min - EPSILON; - for (size_t i = 1; i < layers_sorted.size() - 1; ++i) { - auto& lowr = layers_sorted[i - 1]; - auto& curr = layers_sorted[i]; - auto& higr = layers_sorted[i + 1]; - // "Rounding" suspicious top/bottom contacts - if (curr->layer_type == sltTopContact || curr->layer_type == sltBottomContact) { - // Check adjacent-layer print_z diffs - coordf_t height_low = curr->print_z - lowr->print_z; - coordf_t height_high = higr->print_z - curr->print_z; - if (height_low < thres || height_high < thres) { - // Mark to-be-deleted layer as Unknown type - curr->layer_type = sltUnknown; - } - } - } - // Retains the order - layers_sorted.erase(std::remove_if(layers_sorted.begin(), layers_sorted.end(), [](MyLayer* l) {return l->layer_type == sltUnknown; }), layers_sorted.end()); - } - - int layer_id = 0; - int layer_id_interface = 0; - assert(object.support_layers().empty()); - for (size_t i = 0; i < layers_sorted.size();) { - // Find the last layer with roughly the same print_z, find the minimum layer height of all. - // Due to the floating point inaccuracies, the print_z may not be the same even if in theory they should. - size_t j = i + 1; - coordf_t zmax = layers_sorted[i]->print_z + EPSILON; - for (; j < layers_sorted.size() && layers_sorted[j]->print_z <= zmax; ++j) ; - // Assign an average print_z to the set of layers with nearly equal print_z. - coordf_t zavg = 0.5 * (layers_sorted[i]->print_z + layers_sorted[j - 1]->print_z); - coordf_t height_min = layers_sorted[i]->height; - bool empty = true; - // For snug supports, layers where the direction of the support interface shall change are accounted for. - size_t num_interfaces = 0; - size_t num_top_contacts = 0; - double top_contact_bottom_z = 0; - for (size_t u = i; u < j; ++u) { - MyLayer &layer = *layers_sorted[u]; - if (! layer.polygons.empty()) { - empty = false; - num_interfaces += one_of(layer.layer_type, support_types_interface); - if (layer.layer_type == sltTopContact) { - ++ num_top_contacts; - assert(num_top_contacts <= 1); - // All top contact layers sharing this print_z shall also share bottom_z. - //assert(num_top_contacts == 1 || (top_contact_bottom_z - layer.bottom_z) < EPSILON); - top_contact_bottom_z = layer.bottom_z; - } - } - layer.print_z = zavg; - height_min = std::min(height_min, layer.height); - } - if (! empty) { - // Here the upper_layer and lower_layer pointers are left to null at the support layers, - // as they are never used. These pointers are candidates for removal. - bool this_layer_contacts_only = num_top_contacts > 0 && num_top_contacts == num_interfaces; - size_t this_layer_id_interface = layer_id_interface; - if (this_layer_contacts_only) { - // Find a supporting layer for its interface ID. - for (auto it = object.support_layers().rbegin(); it != object.support_layers().rend(); ++ it) - if (const SupportLayer &other_layer = **it; std::abs(other_layer.print_z - top_contact_bottom_z) < EPSILON) { - // other_layer supports this top contact layer. Assign a different support interface direction to this layer - // from the layer that supports it. - this_layer_id_interface = other_layer.interface_id() + 1; - } - } - object.add_support_layer(layer_id ++, this_layer_id_interface, height_min, zavg); - if (num_interfaces && ! this_layer_contacts_only) - ++ layer_id_interface; - } - i = j; - } +#ifdef SLIC3R_DEBUG + SupportGeneratorLayersPtr layers_sorted = +#endif // SLIC3R_DEBUG + generate_support_layers(object, raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers); BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths"; @@ -1841,17 +1757,16 @@ static inline std::tuple detect_contacts( // Allocate one, possibly two support contact layers. // For "thick" overhangs, one support layer will be generated to support normal extrusions, the other to support the "thick" extrusions. -static inline std::pair new_contact_layer( +static inline std::pair new_contact_layer( const PrintConfig &print_config, const PrintObjectConfig &object_config, const SlicingParameters &slicing_params, const coordf_t support_layer_height_min, const Layer &layer, - std::deque &layer_storage, - tbb::spin_mutex &layer_storage_mutex) + SupportGeneratorLayerStorage &layer_storage) { double print_z, bottom_z, height; - PrintObjectSupportMaterial::MyLayer* bridging_layer = nullptr; + SupportGeneratorLayer* bridging_layer = nullptr; assert(layer.id() >= slicing_params.raft_layers()); size_t layer_id = layer.id() - slicing_params.raft_layers(); @@ -1877,7 +1792,7 @@ static inline std::pair(nullptr, nullptr); + return std::pair(nullptr, nullptr); } const bool has_raft = slicing_params.raft_layers() > 1; const coordf_t min_print_z = has_raft ? slicing_params.raft_contact_top_z : slicing_params.first_print_layer_height; @@ -1911,7 +1826,7 @@ static inline std::pairidx_object_layer_above = layer_id; bridging_layer->print_z = bridging_print_z; if (bridging_print_z == slicing_params.first_print_layer_height) { @@ -1929,7 +1844,7 @@ static inline std::pairprint_z < l2->print_z; }); + std::sort(layers.begin(), layers.end(), [](const SupportGeneratorLayer *l1, const SupportGeneratorLayer *l2) { return l1->print_z < l2->print_z; }); int i = 0; int k = 0; @@ -2103,7 +2018,7 @@ static void merge_contact_layers(const SlicingParameters &slicing_params, double for (; j < (int)layers.size() && layers[j]->print_z < slicing_params.first_print_layer_height + support_layer_height_min - EPSILON; ++ j); if (j > 0) { // Merge the layers layers (0) to (j - 1) into the layers[0]. - PrintObjectSupportMaterial::MyLayer &dst = *layers.front(); + SupportGeneratorLayer &dst = *layers.front(); for (int u = 1; u < j; ++ u) dst.merge(std::move(*layers[u])); // Snap the first layer to the 1st layer height. @@ -2121,7 +2036,7 @@ static void merge_contact_layers(const SlicingParameters &slicing_params, double for (; j < (int)layers.size() && layers[j]->print_z < zmax; ++ j) ; if (i + 1 < j) { // Merge the layers layers (i + 1) to (j - 1) into the layers[i]. - PrintObjectSupportMaterial::MyLayer &dst = *layers[i]; + SupportGeneratorLayer &dst = *layers[i]; for (int u = i + 1; u < j; ++ u) dst.merge(std::move(*layers[u])); } @@ -2205,8 +2120,8 @@ static OverhangCluster* add_overhang(std::vector& clusters, ExP // Generate top contact layers supporting overhangs. // For a soluble interface material synchronize the layer heights with the object, otherwise leave the layer height undefined. // If supports over bed surface only are requested, don't generate contact layers over an object. -PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_layers( - const PrintObject &object, const std::vector &buildplate_covered, MyLayerStorage &layer_storage) const +SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers( + const PrintObject &object, const std::vector &buildplate_covered, SupportGeneratorLayerStorage &layer_storage) const { #ifdef SLIC3R_DEBUG static int iRun = 0; @@ -2217,14 +2132,14 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // BBS: tree support is selected so normal supports need not be generated. // Note we still need to go through the following steps if support is disabled but raft is enabled. if (m_object_config->enable_support.value && (m_object_config->support_type.value != stNormalAuto && m_object_config->support_type.value != stNormal)) { - return MyLayersPtr(); + return SupportGeneratorLayersPtr(); } // Slice support enforcers / support blockers. SupportAnnotations annotations(object, buildplate_covered); // Output layers, sorted by top Z. - MyLayersPtr contact_out; + SupportGeneratorLayersPtr contact_out; BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::top_contact_layers() in parallel - start"; // Determine top contact areas. @@ -2236,7 +2151,6 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // For each overhang layer, two supporting layers may be generated: One for the overhangs extruded with a bridging flow, // and the other for the overhangs extruded with a normal flow. contact_out.assign(num_layers * 2, nullptr); - tbb::spin_mutex layer_storage_mutex; std::vector overhangs_per_layers(num_layers); size_t layer_id_start = this->has_raft() ? 0 : 1; @@ -2260,7 +2174,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ ); // end tbb::parallel_for if (object.print()->canceled()) - return MyLayersPtr(); + return SupportGeneratorLayersPtr(); // check if the sharp tails should be extended higher bool detect_first_sharp_tail_only = false; @@ -2349,7 +2263,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ } if (object.print()->canceled()) - return MyLayersPtr(); + return SupportGeneratorLayersPtr(); // BBS group overhang clusters const bool config_remove_small_overhangs = m_object_config->support_remove_small_overhang.value; @@ -2423,7 +2337,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ } if (object.print()->canceled()) - return MyLayersPtr(); + return SupportGeneratorLayersPtr(); for (size_t layer_id = layer_id_start; layer_id < num_layers; layer_id++) { const Layer& layer = *object.layers()[layer_id]; @@ -2441,7 +2355,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // Now apply the contact areas to the layer where they need to be made. if (!contact_polygons.empty() || !overhang_polygons.empty()) { // Allocate the two empty layers. - auto [new_layer, bridging_layer] = new_contact_layer(*m_print_config, *m_object_config, m_slicing_params, m_support_params.support_layer_height_min, layer, layer_storage, layer_storage_mutex); + auto [new_layer, bridging_layer] = new_contact_layer(*m_print_config, *m_object_config, m_slicing_params, m_support_params.support_layer_height_min, layer, layer_storage); if (new_layer) { // Fill the non-bridging layer with polygons. fill_contact_layer(*new_layer, layer_id, m_slicing_params, @@ -2480,17 +2394,17 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ } // Find the bottom contact layers above the top surfaces of this layer. -static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts( +static inline SupportGeneratorLayer* detect_bottom_contacts( const SlicingParameters &slicing_params, const PrintObjectSupportMaterial::SupportParams &support_params, const PrintObject &object, const Layer &layer, // Existing top contact layers, to which this newly created bottom contact layer will be snapped to guarantee a minimum layer height. - const PrintObjectSupportMaterial::MyLayersPtr &top_contacts, + const SupportGeneratorLayersPtr &top_contacts, // First top contact layer index overlapping with this new bottom interface layer. size_t contact_idx, // To allocate a new layer from. - std::deque &layer_storage, + SupportGeneratorLayerStorage &layer_storage, // To trim the support areas above this bottom interface layer with this newly created bottom interface layer. std::vector &layer_support_areas, // Support areas projected from top to bottom, starting with top support interfaces. @@ -2525,7 +2439,7 @@ static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts( size_t layer_id = layer.id() - slicing_params.raft_layers(); // Allocate a new bottom contact layer. - PrintObjectSupportMaterial::MyLayer &layer_new = layer_allocate(layer_storage, PrintObjectSupportMaterial::sltBottomContact); + SupportGeneratorLayer &layer_new = layer_storage.allocate_unguarded(SupporLayerType::BottomContact); // Grow top surfaces so that interface and support generation are generated // with some spacing from object - it looks we don't need the actual // top shapes so this can be done here @@ -2693,12 +2607,12 @@ static inline std::pair project_support_to_grid(const Layer // Generate bottom contact layers supporting the top contact layers. // For a soluble interface material synchronize the layer heights with the object, // otherwise set the layer height to a bridging flow of a support interface nozzle. -PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_contact_layers_and_layer_support_areas( - const PrintObject &object, const MyLayersPtr &top_contacts, std::vector &buildplate_covered, - MyLayerStorage &layer_storage, std::vector &layer_support_areas) const +SupportGeneratorLayersPtr PrintObjectSupportMaterial::bottom_contact_layers_and_layer_support_areas( + const PrintObject &object, const SupportGeneratorLayersPtr &top_contacts, std::vector &buildplate_covered, + SupportGeneratorLayerStorage &layer_storage, std::vector &layer_support_areas) const { if (top_contacts.empty()) - return MyLayersPtr(); + return SupportGeneratorLayersPtr(); #ifdef SLIC3R_DEBUG static size_t s_iRun = 0; @@ -2715,7 +2629,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta // find object top surfaces // we'll use them to clip our support and detect where does it stick - MyLayersPtr bottom_contacts; + SupportGeneratorLayersPtr bottom_contacts; // There is some support to be built, if there are non-empty top surfaces detected. // Sum of unsupported contact areas above the current layer.print_z. @@ -2734,7 +2648,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta Polygons enforcers_new; #endif // SLIC3R_DEBUG for (; contact_idx >= 0 && top_contacts[contact_idx]->print_z > layer.print_z - EPSILON; -- contact_idx) { - MyLayer &top_contact = *top_contacts[contact_idx]; + SupportGeneratorLayer &top_contact = *top_contacts[contact_idx]; #ifndef SLIC3R_DEBUG Polygons polygons_new; Polygons enforcers_new; @@ -2776,7 +2690,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta #endif // SLIC3R_DEBUG ] { // Find the bottom contact layers above the top surfaces of this layer. - MyLayer *layer_new = detect_bottom_contacts( + SupportGeneratorLayer *layer_new = detect_bottom_contacts( m_slicing_params, m_support_params, object, layer, top_contacts, contact_idx, layer_storage, layer_support_areas, overhangs_for_bottom_contacts #ifdef SLIC3R_DEBUG , iRun, polygons_new @@ -2835,64 +2749,21 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta return bottom_contacts; } -template -IndexType idx_higher_or_equal(const std::vector& vec, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal) -{ - return Layer::idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal); -} - -// FN_LOWER_EQUAL: the provided object pointer has a Z value <= of an internal threshold. -// Find the first item with Z value <= of an internal threshold of fn_lower_equal. -// If no vec item with Z value <= of an internal threshold of fn_lower_equal is found, return -1. -// If the initial idx is < -1, then use binary search. -// Otherwise search linearly downwards. -template -int idx_lower_or_equal(IT begin, IT end, int idx, FN_LOWER_EQUAL fn_lower_equal) -{ - auto size = int(end - begin); - if (size == 0) { - idx = -1; - } else if (idx < -1) { - // First of the batch of layers per thread pool invocation. Use binary search. - int idx_low = 0; - int idx_high = std::max(0, size - 1); - while (idx_low + 1 < idx_high) { - int idx_mid = (idx_low + idx_high) / 2; - if (fn_lower_equal(begin[idx_mid])) - idx_low = idx_mid; - else - idx_high = idx_mid; - } - idx = fn_lower_equal(begin[idx_high]) ? idx_high : - (fn_lower_equal(begin[idx_low ]) ? idx_low : -1); - } else { - // For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search. - while (idx >= 0 && ! fn_lower_equal(begin[idx])) - -- idx; - } - return idx; -} -template -int idx_lower_or_equal(const std::vector &vec, int idx, FN_LOWER_EQUAL fn_lower_equal) -{ - return idx_lower_or_equal(vec.begin(), vec.end(), idx, fn_lower_equal); -} - // Trim the top_contacts layers with the bottom_contacts layers if they overlap, so there would not be enough vertical space for both of them. void PrintObjectSupportMaterial::trim_top_contacts_by_bottom_contacts( - const PrintObject &object, const MyLayersPtr &bottom_contacts, MyLayersPtr &top_contacts) const + const PrintObject &object, const SupportGeneratorLayersPtr &bottom_contacts, SupportGeneratorLayersPtr &top_contacts) const { tbb::parallel_for(tbb::blocked_range(0, int(top_contacts.size())), [&bottom_contacts, &top_contacts](const tbb::blocked_range& range) { int idx_bottom_overlapping_first = -2; // For all top contact layers, counting downwards due to the way idx_higher_or_equal caches the last index to avoid repeated binary search. for (int idx_top = range.end() - 1; idx_top >= range.begin(); -- idx_top) { - MyLayer &layer_top = *top_contacts[idx_top]; + SupportGeneratorLayer &layer_top = *top_contacts[idx_top]; // Find the first bottom layer overlapping with layer_top. - idx_bottom_overlapping_first = idx_lower_or_equal(bottom_contacts, idx_bottom_overlapping_first, [&layer_top](const MyLayer *layer_bottom){ return layer_bottom->bottom_print_z() - EPSILON <= layer_top.bottom_z; }); + idx_bottom_overlapping_first = idx_lower_or_equal(bottom_contacts, idx_bottom_overlapping_first, [&layer_top](const SupportGeneratorLayer *layer_bottom){ return layer_bottom->bottom_print_z() - EPSILON <= layer_top.bottom_z; }); // For all top contact layers overlapping with the thick bottom contact layer: for (int idx_bottom_overlapping = idx_bottom_overlapping_first; idx_bottom_overlapping >= 0; -- idx_bottom_overlapping) { - const MyLayer &layer_bottom = *bottom_contacts[idx_bottom_overlapping]; + const SupportGeneratorLayer &layer_bottom = *bottom_contacts[idx_bottom_overlapping]; assert(layer_bottom.bottom_print_z() - EPSILON <= layer_top.bottom_z); if (layer_top.print_z < layer_bottom.print_z + EPSILON) { // Layers overlap. Trim layer_top with layer_bottom. @@ -2904,16 +2775,16 @@ void PrintObjectSupportMaterial::trim_top_contacts_by_bottom_contacts( }); } -PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_intermediate_support_layers( +SupportGeneratorLayersPtr PrintObjectSupportMaterial::raft_and_intermediate_support_layers( const PrintObject &object, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayerStorage &layer_storage) const + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayerStorage &layer_storage) const { - MyLayersPtr intermediate_layers; + SupportGeneratorLayersPtr intermediate_layers; // Collect and sort the extremes (bottoms of the top contacts and tops of the bottom contacts). - MyLayersPtr extremes; + SupportGeneratorLayersPtr extremes; extremes.reserve(top_contacts.size() + bottom_contacts.size()); for (size_t i = 0; i < top_contacts.size(); ++ i) // Bottoms of the top contact layers. In case of non-soluble supports, @@ -2925,18 +2796,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int if (extremes.empty()) return intermediate_layers; - auto layer_extreme_lower = [](const MyLayer *l1, const MyLayer *l2) { + auto layer_extreme_lower = [](const SupportGeneratorLayer *l1, const SupportGeneratorLayer *l2) { coordf_t z1 = l1->extreme_z(); coordf_t z2 = l2->extreme_z(); // If the layers are aligned, return the top contact surface first. - return z1 < z2 || (z1 == z2 && l1->layer_type == PrintObjectSupportMaterial::sltTopContact && l2->layer_type == PrintObjectSupportMaterial::sltBottomContact); + return z1 < z2 || (z1 == z2 && l1->layer_type == SupporLayerType::TopContact && l2->layer_type == SupporLayerType::BottomContact); }; std::sort(extremes.begin(), extremes.end(), layer_extreme_lower); assert(extremes.empty() || (extremes.front()->extreme_z() > m_slicing_params.raft_interface_top_z - EPSILON && (m_slicing_params.raft_layers() == 1 || // only raft contact layer - extremes.front()->layer_type == sltTopContact || // first extreme is a top contact layer + extremes.front()->layer_type == SupporLayerType::TopContact || // first extreme is a top contact layer extremes.front()->extreme_z() > m_slicing_params.first_print_layer_height - EPSILON))); bool synchronize = this->synchronize_layers(); @@ -2948,7 +2819,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > m_support_params.support_layer_height_min - EPSILON); assert(extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > 0. || extremes[i]->layer_type == extremes[i-1]->layer_type || - (extremes[i]->layer_type == sltBottomContact && extremes[i - 1]->layer_type == sltTopContact)); + (extremes[i]->layer_type == SupporLayerType::BottomContact && extremes[i - 1]->layer_type == SupporLayerType::TopContact)); } #endif @@ -2961,19 +2832,19 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int if (! extremes.empty() && std::abs(extremes.front()->extreme_z() - m_slicing_params.raft_interface_top_z) < EPSILON) { // This is a raft contact layer, its height has been decided in this->top_contact_layers(). // Ignore this layer when calculating the intermediate support layers. - assert(extremes.front()->layer_type == sltTopContact); + assert(extremes.front()->layer_type == SupporLayerType::TopContact); ++ idx_extreme_first; } for (size_t idx_extreme = idx_extreme_first; idx_extreme < extremes.size(); ++ idx_extreme) { - MyLayer *extr2 = extremes[idx_extreme]; + SupportGeneratorLayer *extr2 = extremes[idx_extreme]; coordf_t extr2z = extr2->extreme_z(); if (std::abs(extr2z - m_slicing_params.first_print_layer_height) < EPSILON) { // This is a bottom of a synchronized (or soluble) top contact layer, its height has been decided in this->top_contact_layers(). - assert(extr2->layer_type == sltTopContact); + assert(extr2->layer_type == SupporLayerType::TopContact); assert(std::abs(extr2->bottom_z - m_slicing_params.first_print_layer_height) < EPSILON); assert(extr2->print_z >= m_slicing_params.first_print_layer_height + m_support_params.support_layer_height_min - EPSILON); if (intermediate_layers.empty() || intermediate_layers.back()->print_z < m_slicing_params.first_print_layer_height) { - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); layer_new.bottom_z = 0.; layer_new.print_z = m_slicing_params.first_print_layer_height; layer_new.height = m_slicing_params.first_print_layer_height; @@ -2983,11 +2854,11 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int } assert(extr2z >= m_slicing_params.raft_interface_top_z + EPSILON); assert(extr2z >= m_slicing_params.first_print_layer_height + EPSILON); - MyLayer *extr1 = (idx_extreme == idx_extreme_first) ? nullptr : extremes[idx_extreme - 1]; + SupportGeneratorLayer *extr1 = (idx_extreme == idx_extreme_first) ? nullptr : extremes[idx_extreme - 1]; // Fuse a support layer firmly to the raft top interface (not to the raft contacts). coordf_t extr1z = (extr1 == nullptr) ? m_slicing_params.raft_interface_top_z : extr1->extreme_z(); assert(extr2z >= extr1z); - assert(extr2z > extr1z || (extr1 != nullptr && extr2->layer_type == sltBottomContact)); + assert(extr2z > extr1z || (extr1 != nullptr && extr2->layer_type == SupporLayerType::BottomContact)); if (std::abs(extr1z) < EPSILON) { // This layer interval starts with the 1st layer. Print the 1st layer using the prescribed 1st layer thickness. // assert(! m_slicing_params.has_raft()); RaftingEdition: unclear where the issue is: assert fails with 1-layer raft & base supports @@ -2995,7 +2866,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int // At this point only layers above first_print_layer_heigth + EPSILON are expected as the other cases were captured earlier. assert(extr2z >= m_slicing_params.first_print_layer_height + EPSILON); // Generate a new intermediate layer. - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); layer_new.bottom_z = 0.; layer_new.print_z = extr1z = m_slicing_params.first_print_layer_height; layer_new.height = extr1z; @@ -3015,7 +2886,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int ++ idx_layer_object; if (idx_layer_object == 0 && extr1z == m_slicing_params.raft_interface_top_z) { // Insert one base support layer below the object. - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); layer_new.print_z = m_slicing_params.object_print_z_min; layer_new.bottom_z = m_slicing_params.raft_interface_top_z; layer_new.height = layer_new.print_z - layer_new.bottom_z; @@ -3023,7 +2894,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int } // Emit all intermediate support layers synchronized with object layers up to extr2z. for (; idx_layer_object < object.layers().size() && object.layers()[idx_layer_object]->print_z < extr2z + EPSILON; ++ idx_layer_object) { - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); layer_new.print_z = object.layers()[idx_layer_object]->print_z; layer_new.height = object.layers()[idx_layer_object]->height; layer_new.bottom_z = (idx_layer_object > 0) ? object.layers()[idx_layer_object - 1]->print_z : (layer_new.print_z - layer_new.height); @@ -3035,13 +2906,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int size_t n_layers_extra = size_t(ceil(dist / m_slicing_params.max_suport_layer_height)); assert(n_layers_extra > 0); coordf_t step = dist / coordf_t(n_layers_extra); - if (extr1 != nullptr && extr1->layer_type == sltTopContact && + if (extr1 != nullptr && extr1->layer_type == SupporLayerType::TopContact && extr1->print_z + m_support_params.support_layer_height_min > extr1->bottom_z + step) { // The bottom extreme is a bottom of a top surface. Ensure that the gap // between the 1st intermediate layer print_z and extr1->print_z is not too small. assert(extr1->bottom_z + m_support_params.support_layer_height_min < extr1->print_z + EPSILON); // Generate the first intermediate layer. - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); layer_new.bottom_z = extr1->bottom_z; layer_new.print_z = extr1z = extr1->print_z; layer_new.height = extr1->height; @@ -3053,7 +2924,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int // Continue printing the other layers up to extr2z. step = dist / coordf_t(n_layers_extra); } - if (! m_slicing_params.soluble_interface && extr2->layer_type == sltTopContact) { + if (! m_slicing_params.soluble_interface && extr2->layer_type == SupporLayerType::TopContact) { // This is a top interface layer, which does not have a height assigned yet. Do it now. assert(extr2->height == 0.); assert(extr1z > m_slicing_params.first_print_layer_height - EPSILON); @@ -3065,7 +2936,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int coordf_t extr2z_large_steps = extr2z; // Take the largest allowed step in the Z axis until extr2z_large_steps is reached. for (size_t i = 0; i < n_layers_extra; ++ i) { - MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate); + SupportGeneratorLayer &layer_new = layer_storage.allocate(SupporLayerType::Intermediate); if (i + 1 == n_layers_extra) { // Last intermediate layer added. Align the last entered layer with extr2z_large_steps exactly. layer_new.bottom_z = (i == 0) ? extr1z : intermediate_layers.back()->print_z; @@ -3126,9 +2997,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int // Also the bottom/top_contacts shall have a layer thickness assigned already. void PrintObjectSupportMaterial::generate_base_layers( const PrintObject &object, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayersPtr &intermediate_layers, + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayersPtr &intermediate_layers, const std::vector &layer_support_areas) const { #ifdef SLIC3R_DEBUG @@ -3152,7 +3023,7 @@ void PrintObjectSupportMaterial::generate_base_layers( { BOOST_LOG_TRIVIAL(trace) << "Support generator - generate_base_layers - creating layer " << idx_intermediate << " of " << intermediate_layers.size(); - MyLayer &layer_intermediate = *intermediate_layers[idx_intermediate]; + SupportGeneratorLayer &layer_intermediate = *intermediate_layers[idx_intermediate]; // Layers must be sorted by print_z. assert(idx_intermediate == 0 || layer_intermediate.print_z >= intermediate_layers[idx_intermediate - 1]->print_z); @@ -3175,10 +3046,10 @@ void PrintObjectSupportMaterial::generate_base_layers( // 4) base.print_z > top.bottom_z && base.bottom_z < top.bottom_z -> Base overlaps with top.bottom_z. This must not happen. // 5) base.print_z <= top.print_z && base.bottom_z >= top.bottom_z -> Base is fully inside top. Trim base by top. idx_top_contact_above = idx_lower_or_equal(top_contacts, idx_top_contact_above, - [&layer_intermediate](const MyLayer *layer){ return layer->bottom_z <= layer_intermediate.print_z - EPSILON; }); + [&layer_intermediate](const SupportGeneratorLayer *layer){ return layer->bottom_z <= layer_intermediate.print_z - EPSILON; }); // Collect all the top_contact layer intersecting with this layer. for (int idx_top_contact_overlapping = idx_top_contact_above; idx_top_contact_overlapping >= 0; -- idx_top_contact_overlapping) { - MyLayer &layer_top_overlapping = *top_contacts[idx_top_contact_overlapping]; + SupportGeneratorLayer &layer_top_overlapping = *top_contacts[idx_top_contact_overlapping]; if (layer_top_overlapping.print_z < layer_intermediate.bottom_z + EPSILON) break; // Base must not overlap with top.bottom_z. @@ -3195,7 +3066,7 @@ void PrintObjectSupportMaterial::generate_base_layers( polygons_new = layer_support_areas.front(); double first_layer_z = object.layers().front()->print_z; for (int i = idx_top_contact_above + 1; i < int(top_contacts.size()); ++ i) { - MyLayer &contacts = *top_contacts[i]; + SupportGeneratorLayer &contacts = *top_contacts[i]; if (contacts.print_z > first_layer_z + EPSILON) break; assert(contacts.bottom_z > layer_intermediate.print_z - EPSILON); @@ -3212,10 +3083,10 @@ void PrintObjectSupportMaterial::generate_base_layers( // 4) base.print_z > bottom.print_z && base.bottom_z >= bottom.print_z -> Base overlaps with bottom.print_z. This must not happen. // 5) base.print_z <= bottom.print_z && base.bottom_z >= bottom.bottom_z -> Base is fully inside top. Trim base by top. idx_bottom_contact_overlapping = idx_lower_or_equal(bottom_contacts, idx_bottom_contact_overlapping, - [&layer_intermediate](const MyLayer *layer){ return layer->bottom_print_z() <= layer_intermediate.print_z - EPSILON; }); + [&layer_intermediate](const SupportGeneratorLayer *layer){ return layer->bottom_print_z() <= layer_intermediate.print_z - EPSILON; }); // Collect all the bottom_contacts layer intersecting with this layer. for (int i = idx_bottom_contact_overlapping; i >= 0; -- i) { - MyLayer &layer_bottom_overlapping = *bottom_contacts[i]; + SupportGeneratorLayer &layer_bottom_overlapping = *bottom_contacts[i]; if (layer_bottom_overlapping.print_z < layer_intermediate.bottom_print_z() + EPSILON) break; // Base must not overlap with bottom.top_z. @@ -3245,7 +3116,7 @@ void PrintObjectSupportMaterial::generate_base_layers( polygons_new, polygons_trimming, ApplySafetyOffset::Yes); // safety offset to merge the touching source polygons - layer_intermediate.layer_type = sltBase; + layer_intermediate.layer_type = SupporLayerType::Base; #if 0 // coordf_t fillet_radius_scaled = scale_(m_object_config->support_base_pattern_spacing); @@ -3267,7 +3138,7 @@ void PrintObjectSupportMaterial::generate_base_layers( BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::generate_base_layers() in parallel - end"; #ifdef SLIC3R_DEBUG - for (MyLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++it) + for (SupportGeneratorLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++it) ::Slic3r::SVG::export_expolygons( debug_out_path("support-intermediate-layers-untrimmed-%d-%lf.svg", iRun, (*it)->print_z), union_ex((*it)->polygons)); @@ -3279,7 +3150,7 @@ void PrintObjectSupportMaterial::generate_base_layers( void PrintObjectSupportMaterial::trim_support_layers_by_object( const PrintObject &object, - MyLayersPtr &support_layers, + SupportGeneratorLayersPtr &support_layers, const coordf_t gap_extra_above, const coordf_t gap_extra_below, const coordf_t gap_xy) const @@ -3288,10 +3159,10 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( // Collect non-empty layers to be processed in parallel. // This is a good idea as pulling a thread from a thread pool for an empty task is expensive. - MyLayersPtr nonempty_layers; + SupportGeneratorLayersPtr nonempty_layers; nonempty_layers.reserve(support_layers.size()); for (size_t idx_layer = 0; idx_layer < support_layers.size(); ++ idx_layer) { - MyLayer *support_layer = support_layers[idx_layer]; + SupportGeneratorLayer *support_layer = support_layers[idx_layer]; if (! support_layer->polygons.empty() && support_layer->print_z >= m_slicing_params.raft_contact_top_z + EPSILON) // Non-empty support layer and not a raft layer. nonempty_layers.push_back(support_layer); @@ -3304,7 +3175,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( [this, &object, &nonempty_layers, gap_extra_above, gap_extra_below, gap_xy_scaled](const tbb::blocked_range& range) { size_t idx_object_layer_overlapping = size_t(-1); - auto is_layers_overlap = [](const MyLayer& support_layer, const Layer& object_layer, coordf_t bridging_height = 0.f) -> bool { + auto is_layers_overlap = [](const SupportGeneratorLayer& support_layer, const Layer& object_layer, coordf_t bridging_height = 0.f) -> bool { if (std::abs(support_layer.print_z - object_layer.print_z) < EPSILON) return true; @@ -3318,7 +3189,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( return false; }; for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) { - MyLayer &support_layer = *nonempty_layers[idx_layer]; + SupportGeneratorLayer &support_layer = *nonempty_layers[idx_layer]; // BOOST_LOG_TRIVIAL(trace) << "Support generator - trim_support_layers_by_object - trimmming non-empty layer " << idx_layer << " of " << nonempty_layers.size(); assert(! support_layer.polygons.empty() && support_layer.print_z >= m_slicing_params.raft_contact_top_z + EPSILON); // Find the overlapping object layers including the extra above / below gap. @@ -3378,13 +3249,13 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::trim_support_layers_by_object() in parallel - end"; } -PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base( +SupportGeneratorLayersPtr PrintObjectSupportMaterial::generate_raft_base( const PrintObject &object, - const MyLayersPtr &top_contacts, - const MyLayersPtr &interface_layers, - const MyLayersPtr &base_interface_layers, - const MyLayersPtr &base_layers, - MyLayerStorage &layer_storage) const + const SupportGeneratorLayersPtr &top_contacts, + const SupportGeneratorLayersPtr &interface_layers, + const SupportGeneratorLayersPtr &base_interface_layers, + const SupportGeneratorLayersPtr &base_layers, + SupportGeneratorLayerStorage &layer_storage) const { // If there is brim to be generated, calculate the trimming regions. Polygons brim; @@ -3420,10 +3291,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf // How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed. const float inflate_factor_fine = float(scale_((m_slicing_params.raft_layers() > 1) ? 0.5 : EPSILON)); const float inflate_factor_1st_layer = std::max(0.f, float(scale_(object.config().raft_first_layer_expansion)) - inflate_factor_fine); - MyLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front(); - MyLayer *interfaces = interface_layers .empty() ? nullptr : interface_layers .front(); - MyLayer *base_interfaces = base_interface_layers.empty() ? nullptr : base_interface_layers.front(); - MyLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front(); + SupportGeneratorLayer *contacts = top_contacts .empty() ? nullptr : top_contacts .front(); + SupportGeneratorLayer *interfaces = interface_layers .empty() ? nullptr : interface_layers .front(); + SupportGeneratorLayer *base_interfaces = base_interface_layers.empty() ? nullptr : base_interface_layers.front(); + SupportGeneratorLayer *columns_base = base_layers .empty() ? nullptr : base_layers .front(); if (contacts != nullptr && contacts->print_z > std::max(m_slicing_params.first_print_layer_height, m_slicing_params.raft_contact_top_z) + EPSILON) // This is not the raft contact layer. contacts = nullptr; @@ -3446,7 +3317,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf polygons_append(interface_polygons, expand(base_interfaces->polygons, inflate_factor_fine, SUPPORT_SURFACES_OFFSET_PARAMETERS)); // Output vector. - MyLayersPtr raft_layers; + SupportGeneratorLayersPtr raft_layers; if (m_slicing_params.raft_layers() > 1) { Polygons base; @@ -3465,7 +3336,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf // Do not add the raft contact layer, only add the raft layers below the contact layer. // Insert the 1st layer. { - MyLayer &new_layer = layer_allocate(layer_storage, (m_slicing_params.base_raft_layers > 0) ? sltRaftBase : sltRaftInterface); + SupportGeneratorLayer &new_layer = layer_storage.allocate((m_slicing_params.base_raft_layers > 0) ? SupporLayerType::RaftBase : SupporLayerType::RaftInterface); raft_layers.push_back(&new_layer); new_layer.print_z = m_slicing_params.first_print_layer_height; new_layer.height = m_slicing_params.first_print_layer_height; @@ -3475,7 +3346,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf // Insert the base layers. for (size_t i = 1; i < m_slicing_params.base_raft_layers; ++ i) { coordf_t print_z = raft_layers.back()->print_z; - MyLayer &new_layer = layer_allocate(layer_storage, sltRaftBase); + SupportGeneratorLayer &new_layer = layer_storage.allocate(SupporLayerType::RaftBase); raft_layers.push_back(&new_layer); new_layer.print_z = print_z + m_slicing_params.base_raft_layer_height; new_layer.height = m_slicing_params.base_raft_layer_height; @@ -3485,7 +3356,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf // Insert the interface layers. for (size_t i = 1; i < m_slicing_params.interface_raft_layers; ++ i) { coordf_t print_z = raft_layers.back()->print_z; - MyLayer &new_layer = layer_allocate(layer_storage, sltRaftInterface); + SupportGeneratorLayer &new_layer = layer_storage.allocate(SupporLayerType::RaftInterface); raft_layers.push_back(&new_layer); new_layer.print_z = print_z + m_slicing_params.interface_raft_layer_height; new_layer.height = m_slicing_params.interface_raft_layer_height; @@ -3531,17 +3402,17 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf } // Convert some of the intermediate layers into top/bottom interface layers as well as base interface layers. -std::pair PrintObjectSupportMaterial::generate_interface_layers( - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayersPtr &intermediate_layers, - MyLayerStorage &layer_storage) const +std::pair PrintObjectSupportMaterial::generate_interface_layers( + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayersPtr &intermediate_layers, + SupportGeneratorLayerStorage &layer_storage) const { // my $area_threshold = $self->interface_flow->scaled_spacing ** 2; - std::pair base_and_interface_layers; - MyLayersPtr &interface_layers = base_and_interface_layers.first; - MyLayersPtr &base_interface_layers = base_and_interface_layers.second; + std::pair base_and_interface_layers; + SupportGeneratorLayersPtr &interface_layers = base_and_interface_layers.first; + SupportGeneratorLayersPtr &base_interface_layers = base_and_interface_layers.second; // distinguish between interface and base interface layers // Contact layer is considered an interface layer, therefore run the following block only if support_interface_top_layers > 1. @@ -3577,10 +3448,9 @@ std::pair(m_object_config->support_closing_radius.value); - tbb::spin_mutex layer_storage_mutex; // Insert a new layer into base_interface_layers, if intersection with base exists. - auto insert_layer = [&layer_storage, &layer_storage_mutex, snug_supports, closing_distance, smoothing_distance, minimum_island_radius]( - MyLayer &intermediate_layer, Polygons &bottom, Polygons &&top, const Polygons *subtract, SupporLayerType type) -> MyLayer* { + auto insert_layer = [&layer_storage, snug_supports, closing_distance, smoothing_distance, minimum_island_radius]( + SupportGeneratorLayer &intermediate_layer, Polygons &bottom, Polygons &&top, const Polygons *subtract, SupporLayerType type) -> SupportGeneratorLayer* { assert(! bottom.empty() || ! top.empty()); // Merge top into bottom, unite them with a safety offset. append(bottom, std::move(top)); @@ -3594,7 +3464,7 @@ std::pair::max() : intermediate_layers[std::min(num_intermediate - 1, idx_intermediate_layer + num_interface_layers_only_top - 1)]->print_z; // Move idx_top_contact_first up until above the current print_z. - idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const MyLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON + idx_top_contact_first = idx_higher_or_equal(top_contacts, idx_top_contact_first, [&intermediate_layer](const SupportGeneratorLayer *layer){ return layer->print_z >= intermediate_layer.print_z; }); // - EPSILON // Collect the top contact areas above this intermediate layer, below top_z. for (int idx_top_contact = idx_top_contact_first; idx_top_contact < int(top_contacts.size()); ++ idx_top_contact) { - const MyLayer &top_contact_layer = *top_contacts[idx_top_contact]; + const SupportGeneratorLayer &top_contact_layer = *top_contacts[idx_top_contact]; //FIXME maybe this adds one interface layer in excess? if (top_contact_layer.bottom_z - EPSILON > top_z) break; @@ -3664,26 +3534,26 @@ std::pair::max() : intermediate_layers[std::max(0, idx_intermediate_layer - num_interface_layers_only_bottom)]->bottom_z; // Move idx_bottom_contact_first up until touching bottom_z. - idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const MyLayer *layer){ return layer->print_z >= bottom_z - EPSILON; }); + idx_bottom_contact_first = idx_higher_or_equal(bottom_contacts, idx_bottom_contact_first, [bottom_z](const SupportGeneratorLayer *layer){ return layer->print_z >= bottom_z - EPSILON; }); // Collect the top contact areas above this intermediate layer, below top_z. for (int idx_bottom_contact = idx_bottom_contact_first; idx_bottom_contact < int(bottom_contacts.size()); ++ idx_bottom_contact) { - const MyLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact]; + const SupportGeneratorLayer &bottom_contact_layer = *bottom_contacts[idx_bottom_contact]; if (bottom_contact_layer.print_z - EPSILON > intermediate_layer.bottom_z) break; polygons_append(bottom_contact_layer.print_z - EPSILON > bottom_interface_z ? polygons_bottom_contact_projected_interface : polygons_bottom_contact_projected_base, bottom_contact_layer.polygons); } } - MyLayer *interface_layer = nullptr; + SupportGeneratorLayer *interface_layer = nullptr; if (! polygons_bottom_contact_projected_interface.empty() || ! polygons_top_contact_projected_interface.empty()) { interface_layer = insert_layer( intermediate_layer, polygons_bottom_contact_projected_interface, std::move(polygons_top_contact_projected_interface), nullptr, - polygons_top_contact_projected_interface.empty() ? sltBottomInterface : sltTopInterface); + polygons_top_contact_projected_interface.empty() ? SupporLayerType::BottomInterface : SupporLayerType::TopInterface); interface_layers[idx_intermediate_layer] = interface_layer; } if (! polygons_bottom_contact_projected_base.empty() || ! polygons_top_contact_projected_base.empty()) base_interface_layers[idx_intermediate_layer] = insert_layer( intermediate_layer, polygons_bottom_contact_projected_base, std::move(polygons_top_contact_projected_base), - interface_layer ? &interface_layer->polygons : nullptr, sltBase); + interface_layer ? &interface_layer->polygons : nullptr, SupporLayerType::Base); } }); @@ -3859,7 +3729,7 @@ struct MyLayerExtruded } // The source layer. It carries the height and extrusion type (bridging / non bridging, extrusion height). - PrintObjectSupportMaterial::MyLayer *layer { nullptr }; + SupportGeneratorLayer *layer { nullptr }; // Collect extrusions. They will be exported sorted by the bottom height. ExtrusionEntitiesPtr extrusions; @@ -4127,9 +3997,9 @@ static std::string dbg_index_to_color(int idx) void modulate_extrusion_by_overlapping_layers( // Extrusions generated for this_layer. ExtrusionEntitiesPtr &extrusions_in_out, - const PrintObjectSupportMaterial::MyLayer &this_layer, + const SupportGeneratorLayer &this_layer, // Multiple layers overlapping with this_layer, sorted bottom up. - const PrintObjectSupportMaterial::MyLayersPtr &overlapping_layers) + const SupportGeneratorLayersPtr &overlapping_layers) { size_t n_overlapping_layers = overlapping_layers.size(); if (n_overlapping_layers == 0 || extrusions_in_out.empty()) @@ -4166,7 +4036,7 @@ void modulate_extrusion_by_overlapping_layers( ++ iRun; BoundingBox bbox; for (size_t i_overlapping_layer = 0; i_overlapping_layer < n_overlapping_layers; ++ i_overlapping_layer) { - const PrintObjectSupportMaterial::MyLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; + const SupportGeneratorLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; bbox.merge(get_extents(overlapping_layer.polygons)); } for (ExtrusionEntitiesPtr::const_iterator it = extrusions_in_out.begin(); it != extrusions_in_out.end(); ++ it) { @@ -4179,13 +4049,13 @@ void modulate_extrusion_by_overlapping_layers( // Filled polygons for the overlapping regions. svg.draw(union_ex(this_layer.polygons), dbg_index_to_color(-1), transparency); for (size_t i_overlapping_layer = 0; i_overlapping_layer < n_overlapping_layers; ++ i_overlapping_layer) { - const PrintObjectSupportMaterial::MyLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; + const SupportGeneratorLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; svg.draw(union_ex(overlapping_layer.polygons), dbg_index_to_color(int(i_overlapping_layer)), transparency); } // Contours of the overlapping regions. svg.draw(to_polylines(this_layer.polygons), dbg_index_to_color(-1), scale_(0.2)); for (size_t i_overlapping_layer = 0; i_overlapping_layer < n_overlapping_layers; ++ i_overlapping_layer) { - const PrintObjectSupportMaterial::MyLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; + const SupportGeneratorLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; svg.draw(to_polylines(overlapping_layer.polygons), dbg_index_to_color(int(i_overlapping_layer)), scale_(0.1)); } // Fill extrusion, the source. @@ -4226,7 +4096,7 @@ void modulate_extrusion_by_overlapping_layers( // Fragment the path segments by overlapping layers. The overlapping layers are sorted by an increasing print_z. // Trim by the highest overlapping layer first. for (int i_overlapping_layer = int(n_overlapping_layers) - 1; i_overlapping_layer >= 0; -- i_overlapping_layer) { - const PrintObjectSupportMaterial::MyLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; + const SupportGeneratorLayer &overlapping_layer = *overlapping_layers[i_overlapping_layer]; ExtrusionPathFragment &frag = path_fragments[i_overlapping_layer]; Polygons polygons_trimming = offset(union_ex(overlapping_layer.polygons), float(scale_(0.5*extrusion_width))); frag.polylines = intersection_pl(path_fragments.back().polylines, polygons_trimming); @@ -4317,7 +4187,7 @@ void modulate_extrusion_by_overlapping_layers( ExtrusionPath *path = multipath.paths.empty() ? nullptr : &multipath.paths.back(); if (path != nullptr) { // Verify whether the path is compatible with the current fragment. - assert(this_layer.layer_type == PrintObjectSupportMaterial::sltBottomContact || path->height != frag.height || path->mm3_per_mm != frag.mm3_per_mm); + assert(this_layer.layer_type == SupporLayerType::BottomContact || path->height != frag.height || path->mm3_per_mm != frag.mm3_per_mm); if (path->height != frag.height || path->mm3_per_mm != frag.mm3_per_mm) { path = nullptr; } @@ -4366,12 +4236,12 @@ void modulate_extrusion_by_overlapping_layers( void PrintObjectSupportMaterial::generate_toolpaths( SupportLayerPtrs &support_layers, - const MyLayersPtr &raft_layers, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - const MyLayersPtr &intermediate_layers, - const MyLayersPtr &interface_layers, - const MyLayersPtr &base_interface_layers) const + const SupportGeneratorLayersPtr &raft_layers, + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + const SupportGeneratorLayersPtr &intermediate_layers, + const SupportGeneratorLayersPtr &interface_layers, + const SupportGeneratorLayersPtr &base_interface_layers) const { // loop_interface_processor with a given circle radius. LoopInterfaceProcessor loop_interface_processor(1.5 * m_support_params.support_material_interface_flow.scaled_width()); @@ -4424,7 +4294,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( assert(support_layer_id < raft_layers.size()); SupportLayer &support_layer = *support_layers[support_layer_id]; assert(support_layer.support_fills.entities.empty()); - MyLayer &raft_layer = *raft_layers[support_layer_id]; + SupportGeneratorLayer &raft_layer = *raft_layers[support_layer_id]; std::unique_ptr filler_interface = std::unique_ptr(Fill::new_from_type(m_support_params.interface_fill_pattern)); std::unique_ptr filler_support = std::unique_ptr(Fill::new_from_type(m_support_params.base_fill_pattern)); @@ -4493,7 +4363,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( struct LayerCacheItem { LayerCacheItem(MyLayerExtruded *layer_extruded = nullptr) : layer_extruded(layer_extruded) {} MyLayerExtruded *layer_extruded; - std::vector overlapping; + std::vector overlapping; }; struct LayerCache { MyLayerExtruded bottom_contact_layer; @@ -4556,7 +4426,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( MyLayerExtruded &base_interface_layer = layer_cache.base_interface_layer; // Increment the layer indices to find a layer at support_layer.print_z. { - auto fun = [&support_layer](const MyLayer *l){ return l->print_z >= support_layer.print_z - EPSILON; }; + auto fun = [&support_layer](const SupportGeneratorLayer *l){ return l->print_z >= support_layer.print_z - EPSILON; }; idx_layer_bottom_contact = idx_higher_or_equal(bottom_contacts, idx_layer_bottom_contact, fun); idx_layer_top_contact = idx_higher_or_equal(top_contacts, idx_layer_top_contact, fun); idx_layer_intermediate = idx_higher_or_equal(intermediate_layers, idx_layer_intermediate, fun); @@ -4798,12 +4668,12 @@ void PrintObjectSupportMaterial::generate_toolpaths( // Collect overlapping top/bottom surfaces. layer_cache_item.overlapping.reserve(20); coordf_t bottom_z = layer_cache_item.layer_extruded->layer->bottom_print_z() + EPSILON; - auto add_overlapping = [&layer_cache_item, bottom_z](const MyLayersPtr &layers, size_t idx_top) { + auto add_overlapping = [&layer_cache_item, bottom_z](const SupportGeneratorLayersPtr &layers, size_t idx_top) { for (int i = int(idx_top) - 1; i >= 0 && layers[i]->print_z > bottom_z; -- i) layer_cache_item.overlapping.push_back(layers[i]); }; add_overlapping(top_contacts, idx_layer_top_contact); - if (layer_cache_item.layer_extruded->layer->layer_type == sltBottomContact) { + if (layer_cache_item.layer_extruded->layer->layer_type == SupporLayerType::BottomContact) { // Bottom contact layer may overlap with a base layer, which may be changed to interface layer. add_overlapping(intermediate_layers, idx_layer_intermediate); add_overlapping(interface_layers, idx_layer_interface); diff --git a/src/libslic3r/Support/SupportMaterial.hpp b/src/libslic3r/Support/SupportMaterial.hpp index 861126fcbd..809f9b1611 100644 --- a/src/libslic3r/Support/SupportMaterial.hpp +++ b/src/libslic3r/Support/SupportMaterial.hpp @@ -4,7 +4,8 @@ #include "Flow.hpp" #include "PrintConfig.hpp" #include "Slicing.hpp" - +#include "Fill/FillBase.hpp" +#include "SupportLayer.hpp" namespace Slic3r { class PrintObject; @@ -18,107 +19,6 @@ class PrintObjectConfig; class PrintObjectSupportMaterial { public: - // Support layer type to be used by MyLayer. This type carries a much more detailed information - // about the support layer type than the final support layers stored in a PrintObject. - enum SupporLayerType { - sltUnknown = 0, - // Ratft base layer, to be printed with the support material. - sltRaftBase, - // Raft interface layer, to be printed with the support interface material. - sltRaftInterface, - // Bottom contact layer placed over a top surface of an object. To be printed with a support interface material. - sltBottomContact, - // Dense interface layer, to be printed with the support interface material. - // This layer is separated from an object by an sltBottomContact layer. - sltBottomInterface, - // Sparse base support layer, to be printed with a support material. - sltBase, - // Dense interface layer, to be printed with the support interface material. - // This layer is separated from an object with sltTopContact layer. - sltTopInterface, - // Top contact layer directly supporting an overhang. To be printed with a support interface material. - sltTopContact, - // Some undecided type yet. It will turn into sltBase first, then it may turn into sltBottomInterface or sltTopInterface. - sltIntermediate, - }; - - // A support layer type used internally by the SupportMaterial class. This class carries a much more detailed - // information about the support layer than the layers stored in the PrintObject, mainly - // the MyLayer is aware of the bridging flow and the interface gaps between the object and the support. - class MyLayer - { - public: - void reset() { - *this = MyLayer(); - } - - bool operator==(const MyLayer &layer2) const { - return print_z == layer2.print_z && height == layer2.height && bridging == layer2.bridging; - } - - // Order the layers by lexicographically by an increasing print_z and a decreasing layer height. - bool operator<(const MyLayer &layer2) const { - if (print_z < layer2.print_z) { - return true; - } else if (print_z == layer2.print_z) { - if (height > layer2.height) - return true; - else if (height == layer2.height) { - // Bridging layers first. - return bridging && ! layer2.bridging; - } else - return false; - } else - return false; - } - - void merge(MyLayer &&rhs) { - // The union_() does not support move semantic yet, but maybe one day it will. - this->polygons = union_(this->polygons, std::move(rhs.polygons)); - auto merge = [](std::unique_ptr &dst, std::unique_ptr &src) { - if (! dst || dst->empty()) - dst = std::move(src); - else if (src && ! src->empty()) - *dst = union_(*dst, std::move(*src)); - }; - merge(this->contact_polygons, rhs.contact_polygons); - merge(this->overhang_polygons, rhs.overhang_polygons); - merge(this->enforcer_polygons, rhs.enforcer_polygons); - rhs.reset(); - } - - // For the bridging flow, bottom_print_z will be above bottom_z to account for the vertical separation. - // For the non-bridging flow, bottom_print_z will be equal to bottom_z. - coordf_t bottom_print_z() const { return print_z - height; } - - // To sort the extremes of top / bottom interface layers. - coordf_t extreme_z() const { return (this->layer_type == sltTopContact) ? this->bottom_z : this->print_z; } - - SupporLayerType layer_type { sltUnknown }; - // Z used for printing, in unscaled coordinates. - coordf_t print_z { 0 }; - // Bottom Z of this layer. For soluble layers, bottom_z + height = print_z, - // otherwise bottom_z + gap + height = print_z. - coordf_t bottom_z { 0 }; - // Layer height in unscaled coordinates. - coordf_t height { 0 }; - // Index of a PrintObject layer_id supported by this layer. This will be set for top contact layers. - // If this is not a contact layer, it will be set to size_t(-1). - size_t idx_object_layer_above { size_t(-1) }; - // Index of a PrintObject layer_id, which supports this layer. This will be set for bottom contact layers. - // If this is not a contact layer, it will be set to size_t(-1). - size_t idx_object_layer_below { size_t(-1) }; - // Use a bridging flow when printing this support layer. - bool bridging { false }; - - // Polygons to be filled by the support pattern. - Polygons polygons; - // Currently for the contact layers only. - std::unique_ptr contact_polygons; - std::unique_ptr overhang_polygons; - // Enforcers need to be propagated independently in case the "support on build plate only" option is enabled. - std::unique_ptr enforcer_polygons; - }; struct SupportParams { Flow first_layer_flow; @@ -147,12 +47,6 @@ public: bool with_sheath; }; - // Layers are allocated and owned by a deque. Once a layer is allocated, it is maintained - // up to the end of a generate() method. The layer storage may be replaced by an allocator class in the future, - // which would allocate layers by multiple chunks. - typedef std::deque MyLayerStorage; - typedef std::vector MyLayersPtr; - public: PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params); @@ -176,58 +70,58 @@ private: // Generate top contact layers supporting overhangs. // For a soluble interface material synchronize the layer heights with the object, otherwise leave the layer height undefined. // If supports over bed surface only are requested, don't generate contact layers over an object. - MyLayersPtr top_contact_layers(const PrintObject &object, const std::vector &buildplate_covered, MyLayerStorage &layer_storage) const; + SupportGeneratorLayersPtr top_contact_layers(const PrintObject &object, const std::vector &buildplate_covered, SupportGeneratorLayerStorage &layer_storage) const; // Generate bottom contact layers supporting the top contact layers. // For a soluble interface material synchronize the layer heights with the object, // otherwise set the layer height to a bridging flow of a support interface nozzle. - MyLayersPtr bottom_contact_layers_and_layer_support_areas( - const PrintObject &object, const MyLayersPtr &top_contacts, std::vector &buildplate_covered, - MyLayerStorage &layer_storage, std::vector &layer_support_areas) const; + SupportGeneratorLayersPtr bottom_contact_layers_and_layer_support_areas( + const PrintObject &object, const SupportGeneratorLayersPtr &top_contacts, std::vector &buildplate_covered, + SupportGeneratorLayerStorage &layer_storage, std::vector &layer_support_areas) const; // Trim the top_contacts layers with the bottom_contacts layers if they overlap, so there would not be enough vertical space for both of them. - void trim_top_contacts_by_bottom_contacts(const PrintObject &object, const MyLayersPtr &bottom_contacts, MyLayersPtr &top_contacts) const; + void trim_top_contacts_by_bottom_contacts(const PrintObject &object, const SupportGeneratorLayersPtr &bottom_contacts, SupportGeneratorLayersPtr &top_contacts) const; // Generate raft layers and the intermediate support layers between the bottom contact and top contact surfaces. - MyLayersPtr raft_and_intermediate_support_layers( + SupportGeneratorLayersPtr raft_and_intermediate_support_layers( const PrintObject &object, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayerStorage &layer_storage) const; + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayerStorage &layer_storage) const; // Fill in the base layers with polygons. void generate_base_layers( const PrintObject &object, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayersPtr &intermediate_layers, + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayersPtr &intermediate_layers, const std::vector &layer_support_areas) const; // Generate raft layers, also expand the 1st support layer // in case there is no raft layer to improve support adhesion. - MyLayersPtr generate_raft_base( + SupportGeneratorLayersPtr generate_raft_base( const PrintObject &object, - const MyLayersPtr &top_contacts, - const MyLayersPtr &interface_layers, - const MyLayersPtr &base_interface_layers, - const MyLayersPtr &base_layers, - MyLayerStorage &layer_storage) const; + const SupportGeneratorLayersPtr &top_contacts, + const SupportGeneratorLayersPtr &interface_layers, + const SupportGeneratorLayersPtr &base_interface_layers, + const SupportGeneratorLayersPtr &base_layers, + SupportGeneratorLayerStorage &layer_storage) const; // Turn some of the base layers into base interface layers. // For soluble interfaces with non-soluble bases, print maximum two first interface layers with the base // extruder to improve adhesion of the soluble filament to the base. - std::pair generate_interface_layers( - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - MyLayersPtr &intermediate_layers, - MyLayerStorage &layer_storage) const; + std::pair generate_interface_layers( + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + SupportGeneratorLayersPtr &intermediate_layers, + SupportGeneratorLayerStorage &layer_storage) const; // Trim support layers by an object to leave a defined gap between // the support volume and the object. void trim_support_layers_by_object( const PrintObject &object, - MyLayersPtr &support_layers, + SupportGeneratorLayersPtr &support_layers, const coordf_t gap_extra_above, const coordf_t gap_extra_below, const coordf_t gap_xy) const; @@ -240,12 +134,12 @@ private: // Produce the actual G-code. void generate_toolpaths( SupportLayerPtrs &support_layers, - const MyLayersPtr &raft_layers, - const MyLayersPtr &bottom_contacts, - const MyLayersPtr &top_contacts, - const MyLayersPtr &intermediate_layers, - const MyLayersPtr &interface_layers, - const MyLayersPtr &base_interface_layers) const; + const SupportGeneratorLayersPtr &raft_layers, + const SupportGeneratorLayersPtr &bottom_contacts, + const SupportGeneratorLayersPtr &top_contacts, + const SupportGeneratorLayersPtr &intermediate_layers, + const SupportGeneratorLayersPtr &interface_layers, + const SupportGeneratorLayersPtr &base_interface_layers) const; // Following objects are not owned by SupportMaterial class. const PrintObject *m_object;