From 773c34f906746977d60063c1b5cebe3ecaf07706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Tue, 18 Jun 2024 13:08:33 +0200 Subject: [PATCH] Move skirt smooth path generation to extrusion order --- src/libslic3r/GCode.cpp | 33 ++++++++---------------- src/libslic3r/GCode.hpp | 3 ++- src/libslic3r/GCode/ExtrusionOrder.cpp | 35 +++++++++++++++++++++++++- src/libslic3r/GCode/ExtrusionOrder.hpp | 9 ++++++- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 796550999c..058e821986 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2288,6 +2288,7 @@ std::vector GCodeGenerator::get_sorte const ObjectsLayerToPrint &layers, const LayerTools &layer_tools, const std::vector &instances_to_print, + const GCode::SmoothPathCaches &smooth_path_caches, const bool first_layer ) { // Map from extruder ID to index of skirt loops to be extruded with that extruder. @@ -2331,7 +2332,11 @@ std::vector GCodeGenerator::get_sorte first_layer, layer_tools, instances_to_print, + smooth_path_caches.global(), skirt_loops_per_extruder, + m_enable_loop_clipping, + m_config, + m_scaled_resolution, this->m_writer.extruder()->id(), place_seam, !this->m_brim_done, @@ -2419,7 +2424,7 @@ LayerResult GCodeGenerator::process_layer( using GCode::ExtrusionOrder::ExtruderExtrusions; std::vector extrusions{ - this->get_sorted_extrusions(print, layers, layer_tools, instances_to_print, first_layer)}; + this->get_sorted_extrusions(print, layers, layer_tools, instances_to_print, smooth_path_caches, first_layer)}; std::string gcode; assert(is_decimal_separator_point()); // for the sprintfs @@ -2544,10 +2549,10 @@ LayerResult GCodeGenerator::process_layer( m_avoid_crossing_perimeters.use_external_mp(); Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]))); double mm3_per_mm = layer_skirt_flow.mm3_per_mm(); - for (const auto&[_, loop_entity] : extruder_extrusions.skirt) { + for (const auto&[_, smooth_path] : extruder_extrusions.skirt) { // Adjust flow according to this layer's layer height. //FIXME using the support_material_speed of the 1st object printed. - gcode += this->extrude_skirt(dynamic_cast(*loop_entity), + gcode += this->extrude_skirt(smooth_path, // Override of skirt extrusion parameters. extrude_skirt() will fill in the extrusion width. ExtrusionFlow{ mm3_per_mm, 0., layer_skirt_flow.height() }, smooth_path_caches.global(), "skirt"sv, m_config.support_material_speed.value); @@ -2889,8 +2894,6 @@ static inline bool validate_smooth_path(const GCode::SmoothPath &smooth_path, bo } #endif //NDEBUG -static constexpr const double min_gcode_segment_length = 0.002; - std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed) { // Extrude all loops CCW unless CW movements are prefered. @@ -2910,7 +2913,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC // if polyline was shorter than the clipping distance we'd get a null polyline, so // we discard it in that case. if (m_enable_loop_clipping) - clip_end(smooth_path, scaled(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled(min_gcode_segment_length)); + clip_end(smooth_path, scaled(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled(GCode::ExtrusionOrder::min_gcode_segment_length)); if (smooth_path.empty()) return {}; @@ -2946,25 +2949,9 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC } std::string GCodeGenerator::extrude_skirt( - const ExtrusionLoop &loop_src, const ExtrusionFlow &extrusion_flow_override, + GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed) { - assert(loop_src.is_counter_clockwise()); - const bool reverse_loop = m_config.prefer_clockwise_movements; - - Point seam_point = this->last_position.has_value() ? *this->last_position : Point::Zero(); - GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(loop_src, reverse_loop, m_scaled_resolution, seam_point, scaled(0.0015)); - - // Clip the path to avoid the extruder to get exactly on the first point of the loop; - // if polyline was shorter than the clipping distance we'd get a null polyline, so - // we discard it in that case. - if (m_enable_loop_clipping) - clip_end(smooth_path, scale_(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled(min_gcode_segment_length)); - - if (smooth_path.empty()) - return {}; - - assert(validate_smooth_path(smooth_path, ! m_enable_loop_clipping)); // Extrude along the smooth path. std::string gcode; diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index bd93d6e48a..e9242d6e2d 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -236,6 +236,7 @@ private: const ObjectsLayerToPrint &layers, const LayerTools &layer_tools, const std::vector &instances_to_print, + const GCode::SmoothPathCaches &smooth_path_caches, const bool first_layer ); @@ -282,7 +283,7 @@ private: ); std::string extrude_entity(const ExtrusionEntityReference &entity, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.); std::string extrude_loop(const ExtrusionLoop &loop, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.); - std::string extrude_skirt(const ExtrusionLoop &loop_src, const ExtrusionFlow &extrusion_flow_override, + std::string extrude_skirt(GCode::SmoothPath smooth_path, const ExtrusionFlow &extrusion_flow_override, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed); std::string extrude_multi_path(const ExtrusionMultiPath &multipath, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.); diff --git a/src/libslic3r/GCode/ExtrusionOrder.cpp b/src/libslic3r/GCode/ExtrusionOrder.cpp index a440cd0f7e..0fd9768299 100644 --- a/src/libslic3r/GCode/ExtrusionOrder.cpp +++ b/src/libslic3r/GCode/ExtrusionOrder.cpp @@ -1,4 +1,5 @@ #include "ExtrusionOrder.hpp" +#include "GCode/SmoothPath.hpp" #include "libslic3r/ShortestPath.hpp" namespace Slic3r::GCode::ExtrusionOrder { @@ -453,7 +454,11 @@ std::vector get_extrusions( const bool is_first_layer, const LayerTools &layer_tools, const std::vector &instances_to_print, + const GCode::SmoothPathCache &smooth_path_cache, const std::map> &skirt_loops_per_extruder, + const bool enable_loop_clipping, + const FullPrintConfig &config, + const double scaled_resolution, unsigned current_extruder_id, const SeamPlacingFunciton &place_seam, bool get_brim, @@ -477,7 +482,35 @@ std::vector get_extrusions( if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { const std::pair loops = loops_it->second; for (std::size_t i = loops.first; i < loops.second; ++i) { - extruder_extrusions.skirt.emplace_back(i, print.skirt().entities[i]); + auto loop_src{dynamic_cast(print.skirt().entities[i])}; + if (loop_src != nullptr) { + const Point seam_point = previous_position ? get_instance_point(*previous_position, {0.0, 0.0}) : Point::Zero(); + const bool reverse_loop = config.prefer_clockwise_movements; + // Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns, + // thus empty path segments will not be produced by G-code export. + GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(*loop_src, reverse_loop, scaled_resolution, seam_point, scaled(0.0015)); + + // Clip the path to avoid the extruder to get exactly on the first point of the loop; + // if polyline was shorter than the clipping distance we'd get a null polyline, so + // we discard it in that case. + const auto nozzle_diameter{config.nozzle_diameter.get_at(extruder_id)}; + if (enable_loop_clipping) + clip_end(smooth_path, scale_(nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled(min_gcode_segment_length)); + + if (smooth_path.empty()) + continue; + + assert(validate_smooth_path(smooth_path, ! enable_loop_clipping)); + + for (const SmoothPathElement &element : smooth_path) { + if (!element.path.empty()) { + previous_position = get_gcode_point(element.path.back().point, {0.0, 0.0}); + break; + } + } + + extruder_extrusions.skirt.emplace_back(i, std::move(smooth_path)); + } } } diff --git a/src/libslic3r/GCode/ExtrusionOrder.hpp b/src/libslic3r/GCode/ExtrusionOrder.hpp index ce074a95f9..b9e803c5ed 100644 --- a/src/libslic3r/GCode/ExtrusionOrder.hpp +++ b/src/libslic3r/GCode/ExtrusionOrder.hpp @@ -3,6 +3,7 @@ #include +#include "libslic3r/GCode/SmoothPath.hpp" #include "libslic3r/GCode/WipeTowerIntegration.hpp" #include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/GCode/SeamPlacer.hpp" @@ -98,12 +99,14 @@ std::vector get_normal_extrusions( struct ExtruderExtrusions { unsigned extruder_id; - std::vector> skirt; + std::vector> skirt; ExtrusionEntitiesPtr brim; std::vector> overriden_extrusions; std::vector normal_extrusions; }; +static constexpr const double min_gcode_segment_length = 0.002; + std::vector get_extrusions( const Print &print, const GCode::WipeTowerIntegration *wipe_tower, @@ -111,7 +114,11 @@ std::vector get_extrusions( const bool is_first_layer, const LayerTools &layer_tools, const std::vector &instances_to_print, + const GCode::SmoothPathCache &smooth_path_cache, const std::map> &skirt_loops_per_extruder, + const bool enable_loop_clipping, + const FullPrintConfig &config, + const double scaled_resolution, unsigned current_extruder_id, const SeamPlacingFunciton &place_seam, bool get_brim,