From bee25a4652bae01b28b8a446741e471538f0b441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Thu, 16 May 2024 14:54:17 +0200 Subject: [PATCH] Precalculate noraml and overriden extrusions, before exporting --- src/libslic3r/GCode.cpp | 218 +++++++++++++++++++++++----------------- src/libslic3r/GCode.hpp | 42 +++----- 2 files changed, 141 insertions(+), 119 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index be0fe88fc6..956747bf91 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1961,7 +1961,7 @@ void GCodeGenerator::_print_first_layer_extruder_temperatures(GCodeOutputStream } } -std::vector GCodeGenerator::sort_print_object_instances( +std::vector GCodeGenerator::sort_print_object_instances( const std::vector &object_layers, // Ordering must be defined for normal (non-sequential print). const std::vector *ordering, @@ -2327,7 +2327,7 @@ ExtrusionEntitiesPtr extract_infill_extrusions( assert(dynamic_cast(fills.entities[fill_id])); auto *eec{static_cast(fills.entities[fill_id])}; - if (eec == nullptr || !predicate(*eec, region)) { + if (eec == nullptr || eec->empty() || !predicate(*eec, region)) { continue; } @@ -2360,7 +2360,7 @@ std::vector extract_perimeter_extrusions( // Don't reorder them. assert(dynamic_cast(layerm.perimeters().entities[perimeter_id])); auto *eec = static_cast(layerm.perimeters().entities[perimeter_id]); - if (eec == nullptr || !predicate(*eec, region)) { + if (eec == nullptr || eec->empty() || !predicate(*eec, region)) { continue; } @@ -2741,6 +2741,100 @@ ExtrusionEntityReferences get_support_extrusions( return {}; } +std::vector> get_overriden_extrusions( + const Print &print, + const GCode::ObjectsLayerToPrint &layers, + const LayerTools &layer_tools, + const std::vector &instances_to_print, + const Seams::Placer &seam_placer, + const bool spiral_vase, + const unsigned int extruder_id, + std::optional &previous_position +) { + std::vector> result; + + for (const InstanceToPrint &instance : instances_to_print) { + if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) { + const auto predicate = [&](const ExtrusionEntityCollection &entity_collection, + const PrintRegion ®ion) { + if (!GCode::is_overriden(entity_collection, layer_tools, instance.instance_id)) { + return false; + } + + if (GCode::get_extruder_id( + entity_collection, layer_tools, region, instance.instance_id + ) != extruder_id) { + return false; + } + return true; + }; + + result.emplace_back(get_slices_extrusions( + print, layer, seam_placer, previous_position, spiral_vase, predicate + )); + previous_position = get_last_position(result.back(), print.config().infill_first); + } + } + return result; +} + +struct NormalExtrusions { + ExtrusionEntityReferences support_extrusions; + std::vector slices_extrusions; +}; + +std::vector get_normal_extrusions( + const Print &print, + const GCode::ObjectsLayerToPrint &layers, + const LayerTools &layer_tools, + const std::vector &instances_to_print, + const Seams::Placer &seam_placer, + const bool spiral_vase, + const unsigned int extruder_id, + std::optional &previous_position +) { + std::vector result; + + for (std::size_t i{0}; i < instances_to_print.size(); ++i) { + const InstanceToPrint &instance{instances_to_print[i]}; + result.emplace_back(); + + if (layers[instance.object_layer_to_print_id].support_layer != nullptr) { + result.back().support_extrusions = get_support_extrusions( + extruder_id, + layers[instance.object_layer_to_print_id], + translate_support_extruder(instance.print_object.config().support_material_extruder.value, layer_tools, print.config().filament_soluble), + translate_support_extruder(instance.print_object.config().support_material_interface_extruder.value, layer_tools, print.config().filament_soluble) + ); + previous_position = get_last_position(result.back().support_extrusions); + } + + if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) { + const auto predicate = [&](const ExtrusionEntityCollection &entity_collection, const PrintRegion ®ion){ + if (GCode::is_overriden(entity_collection, layer_tools, instance.instance_id)) { + return false; + } + + if (GCode::get_extruder_id(entity_collection, layer_tools, region, instance.instance_id) != extruder_id) { + return false; + } + return true; + }; + + result.back().slices_extrusions = get_slices_extrusions( + print, + layer, + seam_placer, + previous_position, + spiral_vase, + predicate + ); + previous_position = get_last_position(result.back().slices_extrusions, print.config().infill_first); + } + } + return result; +} + // In sequential mode, process_layer is called once per each object and its copy, // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. // In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated. @@ -2991,93 +3085,46 @@ LayerResult GCodeGenerator::process_layer( std::optional previous_position{this->last_position}; - // We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature): bool is_anything_overridden = layer_tools.wiping_extrusions().is_anything_overridden(); + std::vector> overriden_extrusions; if (is_anything_overridden) { + overriden_extrusions = get_overriden_extrusions( + print, layers, layer_tools, instances_to_print, this->m_seam_placer, + this->m_config.spiral_vase, extruder_id, previous_position + ); + } + const std::vector normal_extrusions{get_normal_extrusions( + print, layers, layer_tools, instances_to_print, this->m_seam_placer, + this->m_config.spiral_vase, extruder_id, previous_position + )}; + + + // We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature): + if (!overriden_extrusions.empty()) { // Extrude wipes. size_t gcode_size_old = gcode.size(); - for (const InstanceToPrint &instance : instances_to_print) { - std::vector slices_extrusions; - if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) { - const auto predicate = [&](const ExtrusionEntityCollection &entity_collection, const PrintRegion ®ion){ - if (entity_collection.entities.empty()) { - return false; - } - if (!GCode::is_overriden(entity_collection, layer_tools, instance.instance_id)) { - return false; - } - - if (GCode::get_extruder_id(entity_collection, layer_tools, region, instance.instance_id) != extruder_id) { - return false; - } - return true; - }; - - slices_extrusions = get_slices_extrusions( - print, - layer, - this->m_seam_placer, - previous_position, - m_config.spiral_vase, - predicate - ); - previous_position = get_last_position(slices_extrusions, print.config().infill_first); - } + for (std::size_t i{0}; i < instances_to_print.size(); ++i) { + const InstanceToPrint &instance{instances_to_print[i]}; this->process_layer_single_object( - gcode, extruder_id, instance, - layers[instance.object_layer_to_print_id], layer_tools, smooth_path_caches.layer_local(), - is_anything_overridden, true /* print_wipe_extrusions */, {}, slices_extrusions); + gcode, instance, layers[instance.object_layer_to_print_id], + smooth_path_caches.layer_local(), {}, overriden_extrusions[i] + ); } if (gcode_size_old < gcode.size()) { gcode+="; PURGING FINISHED\n"; } } + // Extrude normal extrusions. - for (const InstanceToPrint &instance : instances_to_print) { - ExtrusionEntityReferences support_extrusions; - - if (layers[instance.object_layer_to_print_id].support_layer != nullptr) { - support_extrusions = get_support_extrusions( - extruder_id, - layers[instance.object_layer_to_print_id], - translate_support_extruder(instance.print_object.config().support_material_extruder.value, layer_tools, print.config().filament_soluble), - translate_support_extruder(instance.print_object.config().support_material_interface_extruder.value, layer_tools, print.config().filament_soluble) - ); - previous_position = get_last_position(support_extrusions); - } - - std::vector slices_extrusions; - if (const Layer *layer = layers[instance.object_layer_to_print_id].object_layer; layer) { - const auto predicate = [&](const ExtrusionEntityCollection &entity_collection, const PrintRegion ®ion){ - if (entity_collection.entities.empty()) { - return false; - } - if (GCode::is_overriden(entity_collection, layer_tools, instance.instance_id)) { - return false; - } - - if (GCode::get_extruder_id(entity_collection, layer_tools, region, instance.instance_id) != extruder_id) { - return false; - } - return true; - }; - - slices_extrusions = get_slices_extrusions( - print, - layer, - this->m_seam_placer, - previous_position, - m_config.spiral_vase, - predicate - ); - previous_position = get_last_position(slices_extrusions, print.config().infill_first); - } + for (std::size_t i{0}; i < instances_to_print.size(); ++i) { + const InstanceToPrint &instance{instances_to_print[i]}; this->process_layer_single_object( - gcode, extruder_id, instance, - layers[instance.object_layer_to_print_id], layer_tools, smooth_path_caches.layer_local(), - is_anything_overridden, false /* print_wipe_extrusions */, support_extrusions, slices_extrusions); + gcode, instance, layers[instance.object_layer_to_print_id], + smooth_path_caches.layer_local(), normal_extrusions[i].support_extrusions, + normal_extrusions[i].slices_extrusions + ); } } @@ -3159,26 +3206,13 @@ LayerResult GCodeGenerator::process_layer( } void GCodeGenerator::process_layer_single_object( - // output - std::string &gcode, - // Index of the extruder currently active. - const unsigned int extruder_id, - // What object and instance is going to be printed. - const InstanceToPrint &print_instance, - // and the object & support layer of the above. + std::string &gcode, + const InstanceToPrint &print_instance, const ObjectLayerToPrint &layer_to_print, - // Container for extruder overrides (when wiping into object or infill). - const LayerTools &layer_tools, - // Optional smooth path interpolating extrusion polylines. const GCode::SmoothPathCache &smooth_path_cache, - // Is any extrusion possibly marked as wiping extrusion? - const bool is_anything_overridden, - // Round 1 (wiping into object or infill) or round 2 (normal extrusions). - const bool print_wipe_extrusions, const ExtrusionEntityReferences &support_extrusions, const std::vector &slices_extrusions -) -{ +) { const PrintObject &print_object = print_instance.print_object; const Print &print = *print_object.print(); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index a286a8f925..1bf1aad818 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -121,6 +121,18 @@ struct InfillRange { } // namespace GCode +struct InstanceToPrint +{ + InstanceToPrint(size_t object_layer_to_print_id, const PrintObject &print_object, size_t instance_id) : + object_layer_to_print_id(object_layer_to_print_id), print_object(print_object), instance_id(instance_id) {} + + // Index into std::vector, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances. + const size_t object_layer_to_print_id; + const PrintObject &print_object; + // Instance idx of the copy of a print object. + const size_t instance_id; +}; + class GCodeGenerator { public: @@ -291,18 +303,6 @@ private: std::string extrude_multi_path(const ExtrusionMultiPath &multipath, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.); std::string extrude_path(const ExtrusionPath &path, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.); - struct InstanceToPrint - { - InstanceToPrint(size_t object_layer_to_print_id, const PrintObject &print_object, size_t instance_id) : - object_layer_to_print_id(object_layer_to_print_id), print_object(print_object), instance_id(instance_id) {} - - // Index into std::vector, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances. - const size_t object_layer_to_print_id; - const PrintObject &print_object; - // Instance idx of the copy of a print object. - const size_t instance_id; - }; - std::vector sort_print_object_instances( // Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances. const std::vector &layers, @@ -334,22 +334,10 @@ private: // This function will be called for each printing extruder, possibly twice: First for wiping extrusions, second for normal extrusions. void process_layer_single_object( - // output - std::string &gcode, - // Index of the extruder currently active. - const unsigned int extruder_id, - // What object and instance is going to be printed. - const InstanceToPrint &print_instance, - // and the object & support layer of the above. - const ObjectLayerToPrint &layer_to_print, - // Container for extruder overrides (when wiping into object or infill). - const LayerTools &layer_tools, - // Optional smooth path interpolating extrusion polylines. + std::string &gcode, + const InstanceToPrint &print_instance, + const ObjectLayerToPrint &layer_to_print, const GCode::SmoothPathCache &smooth_path_cache, - // Is any extrusion possibly marked as wiping extrusion? - const bool is_anything_overridden, - // Round 1 (wiping into object or infill) or round 2 (normal extrusions). - const bool print_wipe_extrusions, const ExtrusionEntityReferences &support_extrusions, const std::vector &slices_extrusions );