diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 192ecc892f0..89357db28f9 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5269,8 +5269,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, ref_speed, speed, m_config.slowdown_for_curled_perimeters); } variable_speed = std::any_of(new_points.begin(), new_points.end(), - [speed](const ProcessedPoint &p) { return fabs(double(p.speed) - speed) > EPSILON; }); - + [speed](const ProcessedPoint &p) { return fabs(double(p.speed) - speed) > 1; }); // Ignore small speed variations (under 1mm/sec) } double F = speed * 60; // convert mm/sec to mm/min @@ -5727,10 +5726,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } }// ORCA: End of adaptive PA code segment - - if (last_set_speed != new_speed) { + // Ignore small speed variations - emit speed change if the delta between current and new is greater than 60mm/min / 1mm/sec + // Reset speed to F if delta to F is less than 1mm/sec + if ((std::abs(last_set_speed - new_speed) > 60)) { gcode += m_writer.set_speed(new_speed, "", comment); last_set_speed = new_speed; + } else if ((std::abs(F - new_speed) <= 60)) { + gcode += m_writer.set_speed(F, "", comment); + last_set_speed = F; } auto dE = e_per_mm * line_length; if (!this->on_first_layer() && m_small_area_infill_flow_compensator diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index c6c1c102dea..64f7a718a21 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -38,7 +38,8 @@ template estimate_points_properties(const POINTS &input_points, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, float flow_width, - float max_line_length = -1.0f) + float max_line_length = -1.0f, + float min_distance = -1.0f) { bool looped = input_points.front() == input_points.back(); std::function get_prev_index = [](size_t idx, size_t count) { @@ -118,7 +119,13 @@ std::vector estimate_points_properties(const POINTS if ((curr.distance > -boundary_offset && curr.distance < boundary_offset + 2.0f) || (next.distance > -boundary_offset && next.distance < boundary_offset + 2.0f)) { double line_len = (next.position - curr.position).norm(); - if (line_len > 4.0f) { + + // ORCA: Segment path to smaller lines by adding additional points only if the path has an overhang that + // will trigger a slowdown and the path is also reasonably large, i.e. 2mm in length or more + // If there is no overhang in the start/end point, dont segment it. + // Ignore this check if the control of segmentation for overhangs is disabled (min_distance=-1) + if ((min_distance > 0 && ((std::abs(curr.distance) > min_distance) || (std::abs(next.distance) > min_distance)) && line_len >= 2.f) || + (min_distance <= 0 && line_len > 4.0f)) { double a0 = std::clamp((curr.distance + 3 * boundary_offset) / line_len, 0.0, 1.0); double a1 = std::clamp(1.0f - (next.distance + 3 * boundary_offset) / line_len, 0.0, 1.0); double t0 = std::min(a0, a1); @@ -131,7 +138,11 @@ std::vector estimate_points_properties(const POINTS ExtendedPoint new_p{}; new_p.position = p0; new_p.distance = float(p0_dist + boundary_offset); - new_points.push_back(new_p); + if( (std::abs(p0_dist) > min_distance) || (min_distance<=0)){ + // ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change + // or if this option is disabled (min_distance<=0) + new_points.push_back(new_p); + } } if (t1 > 0.0) { auto p1 = curr.position + t1 * (next.position - curr.position); @@ -140,7 +151,11 @@ std::vector estimate_points_properties(const POINTS ExtendedPoint new_p{}; new_p.position = p1; new_p.distance = float(p1_dist + boundary_offset); - new_points.push_back(new_p); + if( (std::abs(p1_dist) > min_distance) || (min_distance<=0)){ + // ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change + // or if this option is disabled (min_distance<=0) + new_points.push_back(new_p); + } } } } @@ -300,9 +315,30 @@ class ExtrusionQualityEstimator last_section = section; } } + + // Orca: Find the smallest overhang distance where speed adjustments begin + float smallest_distance_with_lower_speed = std::numeric_limits::infinity(); // Initialize to a large value + bool found = false; + for (const auto& section : speed_sections) { + if (section.second <= original_speed) { + if (section.first < smallest_distance_with_lower_speed) { + smallest_distance_with_lower_speed = section.first; + found = true; + } + } + } - std::vector extended_points = - estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); + // If a meaningful (i.e. needing slowdown) overhang distance was not found, then we shouldn't split the lines + if (!found) + smallest_distance_with_lower_speed=-1.f; + + // Orca: Pass to the point properties estimator the smallest ovehang distance that triggers a slowdown (smallest_distance_with_lower_speed) + std::vector extended_points = estimate_points_properties + (path.polyline.points, + prev_layer_boundaries[current_object], + path.width, + -1, + smallest_distance_with_lower_speed); const auto width_inv = 1.0f / path.width; std::vector processed_points; processed_points.reserve(extended_points.size()); @@ -323,7 +359,7 @@ class ExtrusionQualityEstimator // The whole segment gets slower unnecesarily. For these long lines, we do additional check whether it is worth slowing down. // NOTE that this is still quite rough approximation, e.g. we are still checking lines only near the middle point // TODO maybe split the lines into smaller segments before running this alg? but can be demanding, and GCode will be huge - if (len > 8) { + if (len > 2) { Vec2d dir = Vec2d(next.position - curr.position) / len; Vec2d right = Vec2d(-dir.y(), dir.x()); @@ -376,7 +412,7 @@ class ExtrusionQualityEstimator t = std::clamp(t, 0.0f, 1.0f); final_speed = (1.0f - t) * speed_sections[section_idx].second + t * speed_sections[section_idx + 1].second; } - return final_speed; + return round(final_speed); }; float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));