From e1275f7307bd98edaaea373bf2f8894e2bb8e3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Wed, 15 May 2024 10:32:39 +0200 Subject: [PATCH] Do not use GCodeGenerator::last_position during extrusion extraction and sorting. --- src/libslic3r/ExtrusionEntity.hpp | 3 +- src/libslic3r/GCode.cpp | 73 ++++++++++++++++++++++++++----- src/libslic3r/GCode.hpp | 6 ++- 3 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 4007d421b1..29f4098273 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -298,7 +298,8 @@ class ExtrusionLoop : public ExtrusionEntity { public: ExtrusionPaths paths; - + Point seam{Point::Zero()}; + ExtrusionLoop() = default; ExtrusionLoop(ExtrusionLoopRole role) : m_loop_role(role) {} ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {} diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3b6df99cb1..33fa2cdf7b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2704,7 +2704,7 @@ ExtrusionEntitiesPtr extract_infill_extrusions( return result; } -std::vector extract_perimeter_extrusions( +std::vector extract_perimeter_extrusions( const Print &print, const Layer *layer, const LayerIsland &island, @@ -2713,7 +2713,7 @@ std::vector extract_perimeter_extrusions( const int extruder_id, const bool overriden ) { - std::vector result; + std::vector result; const LayerRegion &layerm = *layer->get_region(island.perimeters.region()); // PrintObjects own the PrintRegions, thus the pointer to PrintRegion would be unique to a PrintObject, they would not @@ -2723,8 +2723,8 @@ std::vector extract_perimeter_extrusions( for (uint32_t perimeter_id : island.perimeters) { // Extrusions inside islands are expected to be ordered already. // Don't reorder them. - assert(dynamic_cast(layerm.perimeters().entities[perimeter_id])); - const auto *eec = static_cast(layerm.perimeters().entities[perimeter_id]); + assert(dynamic_cast(layerm.perimeters().entities[perimeter_id])); + auto *eec = static_cast(layerm.perimeters().entities[perimeter_id]); if (eec == nullptr) { continue; } @@ -2739,7 +2739,7 @@ std::vector extract_perimeter_extrusions( continue; } - for (const ExtrusionEntity *ee : *eec) { + for (ExtrusionEntity *ee : *eec) { result.push_back(ee); } } @@ -2813,6 +2813,25 @@ std::vector extract_infill_ranges( } return result; } +} // namespace GCode + +void GCodeGenerator::place_seams( + const std::vector &perimeters, std::optional previous_position +) { + std::vector result; + result.reserve(perimeters.size()); + + for (ExtrusionEntity* perimeter : perimeters) { + auto loop{static_cast(perimeter)}; + + Point seam_point{previous_position ? *previous_position : Point::Zero()}; + if (!m_config.spiral_vase && loop != nullptr) { + assert(m_layer != nullptr); + seam_point = this->m_seam_placer.place_seam(m_layer, *loop, seam_point); + loop->seam = seam_point; + } + previous_position = seam_point; + } } std::string GCodeGenerator::extrude_infill_range( @@ -2850,7 +2869,7 @@ std::string GCodeGenerator::extrude_perimeters( const Print &print, const Layer *layer, const LayerIsland &island, - const std::vector &perimeters, + const std::vector &perimeters, const InstanceToPrint &print_instance, const GCode::SmoothPathCache &smooth_path_cache ) { @@ -2969,6 +2988,8 @@ void GCodeGenerator::process_layer_single_object( } } + std::optional previous_position{this->last_position}; + m_layer = layer_to_print.layer(); // To control print speed of the 1st object layer printed over raft interface. m_object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 && @@ -2981,7 +3002,7 @@ void GCodeGenerator::process_layer_single_object( //FIXME order islands? // Sequential tool path ordering of multiple parts within the same object, aka. perimeter tracking (#5511) for (const LayerIsland &island : lslice.islands) { - const std::vector perimeters{GCode::extract_perimeter_extrusions( + const std::vector perimeters{GCode::extract_perimeter_extrusions( print, layer, island, layer_tools, print_instance.instance_id, extruder_id, print_wipe_extrusions )}; @@ -3000,14 +3021,35 @@ void GCodeGenerator::process_layer_single_object( print_wipe_extrusions, false, extruder_id, - this->last_position + previous_position )}; if (!infill_ranges.empty()) { init_layer_delayed(); } gcode += this->extrude_infill_ranges(infill_ranges, "infill", smooth_path_cache); + if (!infill_ranges.empty() && !infill_ranges.back().items.empty()) { + const ExtrusionEntityReference &last_infill{infill_ranges.back().items.back()}; + previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); + } + + this->place_seams(perimeters, previous_position); + if (!perimeters.empty()) { + auto last_perimeter{static_cast(perimeters.back())}; + if (last_perimeter != nullptr) { + previous_position = last_perimeter->seam; + } + } gcode += this->extrude_perimeters(print, layer, island, perimeters, print_instance, smooth_path_cache); } else { + this->place_seams(perimeters, previous_position); + + if (!perimeters.empty()) { + auto last_perimeter{static_cast(perimeters.back())}; + if (last_perimeter != nullptr) { + previous_position = last_perimeter->seam; + } + } + gcode += this->extrude_perimeters(print, layer, island, perimeters, print_instance, smooth_path_cache); const std::vector infill_ranges{GCode::extract_infill_ranges( @@ -3019,11 +3061,15 @@ void GCodeGenerator::process_layer_single_object( print_wipe_extrusions, false, extruder_id, - this->last_position + previous_position )}; if (!infill_ranges.empty()) { init_layer_delayed(); } + if (!infill_ranges.empty() && !infill_ranges.back().items.empty()) { + const ExtrusionEntityReference &last_infill{infill_ranges.back().items.back()}; + previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); + } gcode += this->extrude_infill_ranges(infill_ranges, "infill", smooth_path_cache); } } @@ -3041,12 +3087,17 @@ void GCodeGenerator::process_layer_single_object( print_wipe_extrusions, true, extruder_id, - this->last_position + previous_position )}; if (!ironing_ranges.empty()) { init_layer_delayed(); } + + if (!ironing_ranges.empty() && !ironing_ranges.back().items.empty()) { + const ExtrusionEntityReference &last_infill{ironing_ranges.back().items.back()}; + previous_position = last_infill.flipped() ? last_infill.extrusion_entity().first_point() : last_infill.extrusion_entity().last_point(); + } gcode += this->extrude_infill_ranges(ironing_ranges, "ironing", smooth_path_cache); } } @@ -3190,7 +3241,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC Point seam_point = this->last_position.has_value() ? *this->last_position : Point::Zero(); if (!m_config.spiral_vase && comment_is_perimeter(description)) { assert(m_layer != nullptr); - seam_point = m_seam_placer.place_seam(m_layer, loop_src, seam_point); + seam_point = loop_src.seam; } // 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. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 030709cd73..2518999c52 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -310,11 +310,15 @@ private: // For sequential print, the instance of the object to be printing has to be defined. const size_t single_object_instance_idx); + void place_seams( + const std::vector &perimeters, std::optional previous_position + ); + std::string extrude_perimeters( const Print &print, const Layer *layer, const LayerIsland &island, - const std::vector &perimeters, + const std::vector &perimeters, const InstanceToPrint &print_instance, const GCode::SmoothPathCache &smooth_path_cache );