From b1f5ef354b789bfcf6d1d728e29ee350d1ad403d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 5 Mar 2024 14:33:24 +0100 Subject: [PATCH] SPE-2184: Fix traveling outside the print area during wiping with enabled arcs. --- src/libslic3r/GCode.cpp | 9 ++++-- src/libslic3r/GCode/SmoothPath.cpp | 6 ++++ src/libslic3r/GCode/SmoothPath.hpp | 2 ++ src/libslic3r/GCode/Wipe.cpp | 47 ++++++++++-------------------- src/libslic3r/GCode/Wipe.hpp | 2 +- 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index bbf2870968..90fd1aa15e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2891,7 +2891,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC if (m_wipe.enabled()) { // Wipe will hide the seam. - m_wipe.set_path(std::move(smooth_path), false); + m_wipe.set_path(std::move(smooth_path)); } else if (loop_src.paths.back().role().is_external_perimeter() && m_layer != nullptr && m_config.perimeters.value > 1) { // Only wipe inside if the wipe along the perimeter is disabled. // Make a little move inwards before leaving loop. @@ -2939,7 +2939,7 @@ std::string GCodeGenerator::extrude_skirt( if (m_wipe.enabled()) // Wipe will hide the seam. - m_wipe.set_path(std::move(smooth_path), false); + m_wipe.set_path(std::move(smooth_path)); return gcode; } @@ -2958,7 +2958,10 @@ std::string GCodeGenerator::extrude_multi_path(const ExtrusionMultiPath &multipa std::string gcode; for (GCode::SmoothPathElement &el : smooth_path) gcode += this->_extrude(el.path_attributes, el.path, description, speed); - m_wipe.set_path(std::move(smooth_path), true); + + GCode::reverse(smooth_path); + m_wipe.set_path(std::move(smooth_path)); + // reset acceleration gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); return gcode; diff --git a/src/libslic3r/GCode/SmoothPath.cpp b/src/libslic3r/GCode/SmoothPath.cpp index f27f1f2318..7c2e8b999c 100644 --- a/src/libslic3r/GCode/SmoothPath.cpp +++ b/src/libslic3r/GCode/SmoothPath.cpp @@ -133,6 +133,12 @@ double clip_end(SmoothPath &path, double distance, double min_point_distance_thr return distance; } +void reverse(SmoothPath &path) { + std::reverse(path.begin(), path.end()); + for (SmoothPathElement &path_element : path) + Geometry::ArcWelder::reverse(path_element.path); +} + void SmoothPathCache::interpolate_add(const ExtrusionPath &path, const InterpolationParameters ¶ms) { double tolerance = params.tolerance; diff --git a/src/libslic3r/GCode/SmoothPath.hpp b/src/libslic3r/GCode/SmoothPath.hpp index 83afd60983..8157146f80 100644 --- a/src/libslic3r/GCode/SmoothPath.hpp +++ b/src/libslic3r/GCode/SmoothPath.hpp @@ -33,6 +33,8 @@ std::optional sample_path_point_at_distance_from_end(const SmoothPath &pa // rather discard such a degenerate segment. double clip_end(SmoothPath &path, double distance, double min_point_distance_threshold); +void reverse(SmoothPath &path); + class SmoothPathCache { public: diff --git a/src/libslic3r/GCode/Wipe.cpp b/src/libslic3r/GCode/Wipe.cpp index 774512199a..c773b0f8c3 100644 --- a/src/libslic3r/GCode/Wipe.cpp +++ b/src/libslic3r/GCode/Wipe.cpp @@ -32,40 +32,23 @@ void Wipe::init(const PrintConfig &config, const std::vector &extr this->enable(wipe_xy); } -void Wipe::set_path(SmoothPath &&path, bool reversed) -{ +void Wipe::set_path(SmoothPath &&path) { this->reset_path(); - if (this->enabled() && ! path.empty()) { - if (coord_t wipe_len_max_scaled = scaled(m_wipe_len_max); reversed) { - m_path = std::move(path.back().path); - Geometry::ArcWelder::reverse(m_path); - int64_t len = Geometry::ArcWelder::estimate_path_length(m_path); - for (auto it = std::next(path.rbegin()); len < wipe_len_max_scaled && it != path.rend(); ++ it) { - if (it->path_attributes.role.is_bridge()) - break; // Do not perform a wipe on bridges. - assert(it->path.size() >= 2); - assert(m_path.back().point == it->path.back().point); - if (m_path.back().point != it->path.back().point) - // ExtrusionMultiPath is interrupted in some place. This should not really happen. - break; - len += Geometry::ArcWelder::estimate_path_length(it->path); - m_path.insert(m_path.end(), it->path.rbegin() + 1, it->path.rend()); - } - } else { - m_path = std::move(path.front().path); - int64_t len = Geometry::ArcWelder::estimate_path_length(m_path); - for (auto it = std::next(path.begin()); len < wipe_len_max_scaled && it != path.end(); ++ it) { - if (it->path_attributes.role.is_bridge()) - break; // Do not perform a wipe on bridges. - assert(it->path.size() >= 2); - assert(m_path.back().point == it->path.front().point); - if (m_path.back().point != it->path.front().point) - // ExtrusionMultiPath is interrupted in some place. This should not really happen. - break; - len += Geometry::ArcWelder::estimate_path_length(it->path); - m_path.insert(m_path.end(), it->path.begin() + 1, it->path.end()); - } + if (this->enabled() && !path.empty()) { + const coord_t wipe_len_max_scaled = scaled(m_wipe_len_max); + m_path = std::move(path.front().path); + int64_t len = Geometry::ArcWelder::estimate_path_length(m_path); + for (auto it = std::next(path.begin()); len < wipe_len_max_scaled && it != path.end(); ++it) { + if (it->path_attributes.role.is_bridge()) + break; // Do not perform a wipe on bridges. + assert(it->path.size() >= 2); + assert(m_path.back().point == it->path.front().point); + if (m_path.back().point != it->path.front().point) + // ExtrusionMultiPath is interrupted in some place. This should not really happen. + break; + len += Geometry::ArcWelder::estimate_path_length(it->path); + m_path.insert(m_path.end(), it->path.begin() + 1, it->path.end()); } } diff --git a/src/libslic3r/GCode/Wipe.hpp b/src/libslic3r/GCode/Wipe.hpp index f02a77fa7f..fcd6eeedfc 100644 --- a/src/libslic3r/GCode/Wipe.hpp +++ b/src/libslic3r/GCode/Wipe.hpp @@ -42,7 +42,7 @@ public: if (this->enabled() && path.size() > 1) m_path = std::move(path); } - void set_path(SmoothPath &&path, bool reversed); + void set_path(SmoothPath &&path); void offset_path(const Point &v) { m_offset += v; } std::string wipe(GCodeGenerator &gcodegen, bool toolchange);