From 19eb984d72a27e4b3bd2147f43e3f3e792a4aeae Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 19 Oct 2021 12:05:23 +0200 Subject: [PATCH] SeamPlacer: one more heuristic to get rid of long travels --- src/libslic3r/GCode.cpp | 6 +++--- src/libslic3r/GCode/SeamPlacer.cpp | 29 ++++++++++++++++++++--------- src/libslic3r/GCode/SeamPlacer.hpp | 8 ++++++-- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 137ae1847..97599ca07 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2515,7 +2515,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou loop.split_at(last_pos, false); } else - m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first, EXTRUDER_CONFIG(nozzle_diameter)); + m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first, + EXTRUDER_CONFIG(nozzle_diameter), lower_layer_edge_grid ? lower_layer_edge_grid->get() : nullptr); // 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 @@ -2640,8 +2641,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector(region.perimeters.begin(), region.perimeters.end()), - *m_layer, m_config.seam_position, - m_config.external_perimeters_first, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter), + *m_layer, m_config.seam_position, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter), (m_layer == NULL ? nullptr : m_layer->object()), (lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr)); diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 609ad4d2d..6d082a431 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -293,7 +293,7 @@ void SeamPlacer::init(const Print& print) void SeamPlacer::plan_perimeters(const std::vector perimeters, - const Layer& layer, SeamPosition seam_position, bool external_first, + const Layer& layer, SeamPosition seam_position, Point last_pos, coordf_t nozzle_dmr, const PrintObject* po, const EdgeGrid::Grid* lower_layer_edge_grid) { @@ -315,20 +315,32 @@ void SeamPlacer::plan_perimeters(const std::vector perim layer, seam_position, *dynamic_cast(perimeters[i]), nozzle_dmr, po, lower_layer_edge_grid, last_pos); m_plan[i].external = true; + m_plan[i].seam_position = seam_position; + m_plan[i].layer = &layer; + m_plan[i].po = po; } m_plan[i].pt = last_pos; } } -void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter) +void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter, + const EdgeGrid::Grid* lower_layer_edge_grid) { const double seam_offset = nozzle_diameter; Point seam = last_pos; if (! m_plan.empty() && m_plan_idx < m_plan.size()) { - if (m_plan[m_plan_idx].external) + if (m_plan[m_plan_idx].external) { seam = m_plan[m_plan_idx].pt; + // One more heuristics: if the seam is too far from current nozzle position, + // try to place it again. This can happen in cases where the external perimeter + // does not belong to the preceding ones and they are ordered so they end up + // far from each other. + if ((seam.cast() - last_pos.cast()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.)) + seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter, + m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos); + } else if (! external_first) { // Internal perimeter printed before the external. // First get list of external seams. @@ -342,14 +354,13 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext // First find the line segment closest to an external seam: int path_idx = 0; int line_idx = 0; - size_t ext_seam_idx = -1; + size_t ext_seam_idx = size_t(-1); double min_dist_sqr = std::numeric_limits::max(); - double nozzle_diameter_sqr = std::pow(scale_(nozzle_diameter), 2.); std::vector lines_vect; - for (int i = 0; i < loop.paths.size(); ++i) { + for (int i = 0; i < int(loop.paths.size()); ++i) { lines_vect.emplace_back(loop.paths[i].polyline.lines()); const Lines& lines = lines_vect.back(); - for (int j = 0; j < lines.size(); ++j) { + for (int j = 0; j < int(lines.size()); ++j) { for (size_t k : ext_seams) { double d_sqr = lines[j].distance_to_squared(m_plan[k].pt); if (d_sqr < min_dist_sqr) { @@ -364,7 +375,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext // Only accept seam that is reasonably close. double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.); - if (ext_seam_idx != -1 && min_dist_sqr < limit_dist_sqr) { + if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) { // Now find a projection of the external seam const Lines& lines = lines_vect[path_idx]; Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]); @@ -377,7 +388,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext offset -= dist; const Point* a = &closest; const Point* b = &lines[line_idx].b; - while (++line_idx < lines.size() && offset > 0.) { + while (++line_idx < int(lines.size()) && offset > 0.) { last_offset = offset; offset -= lines[line_idx].length(); a = &lines[line_idx].a; diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 5545fcdf9..57c3532c3 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -49,11 +49,12 @@ public: void plan_perimeters(const std::vector perimeters, - const Layer& layer, SeamPosition seam_position, bool external_first, + const Layer& layer, SeamPosition seam_position, Point last_pos, coordf_t nozzle_dmr, const PrintObject* po, const EdgeGrid::Grid* lower_layer_edge_grid); - void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter); + void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter, + const EdgeGrid::Grid* lower_layer_edge_grid); using TreeType = AABBTreeIndirect::Tree<2, coord_t>; @@ -80,6 +81,9 @@ private: Point pt; bool precalculated = false; bool external = false; + const Layer* layer = nullptr; + SeamPosition seam_position; + const PrintObject* po = nullptr; }; std::vector m_plan; size_t m_plan_idx;