diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 7025cc2f7..335a51696 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2931,7 +2931,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) #if ENABLE_PROCESS_G2_G3_LINES void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise) { - if (!line.has('X') || !line.has('Y') || !line.has('I') || !line.has('J')) + if (!line.has('I') || !line.has('J')) return; // relative center @@ -2962,7 +2962,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc Vec3d relative_start() const { return start - center; } Vec3d relative_end() const { return end - center; } - bool closed() const { return end.isApprox(start); } + bool is_full_circle() const { return std::abs(delta_x()) < EPSILON && std::abs(delta_y()) < EPSILON; } }; Arc arc; @@ -3005,7 +3005,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc const Vec3d rel_arc_end = arc.relative_end(); // arc angle - if (arc.closed()) + if (arc.is_full_circle()) arc.angle = 2.0 * PI; else { arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(), @@ -3057,24 +3057,23 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc // calculate arc segments // reference: // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc() + // https://github.com/prusa3d/Prusa-Firmware/blob/MK3/Firmware/motion_control.cpp // segments count - static const double MM_PER_ARC_SEGMENT = 1.0; - const size_t segments = std::max(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1); + static const double MM_PER_ARC_SEGMENT = 0.5; + const size_t segments = std::ceil(travel_length / MM_PER_ARC_SEGMENT); + assert(segments >= 1); const double theta_per_segment = arc.angle / double(segments); const double z_per_segment = arc.delta_z() / double(segments); const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0; - double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation - double sin_T = theta_per_segment; + const double sq_theta_per_segment = sqr(theta_per_segment); + const double cos_T = 1.0 - 0.5 * sq_theta_per_segment; // Small angle approximation + const double sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6.0; // Small angle approximation AxisCoords prev_target = m_start_position; AxisCoords arc_target; - double sin_Ti; - double cos_Ti; - double r_axisi; - size_t count = 0; // Initialize the linear axis arc_target[Z] = m_start_position[Z]; @@ -3088,22 +3087,23 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc std::string gcode; - for (size_t i = 1; i < segments; ++i) { // Increment (segments-1) - if (count < N_ARC_CORRECTION) { - // Apply vector rotation matrix - r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T; - curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T; - curr_rel_arc_start.y() = r_axisi; - count++; - } - else { - // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. - // Compute exact location by applying transformation matrix from initial radius vector(=-offset). - cos_Ti = ::cos(double(i) * theta_per_segment); - sin_Ti = ::sin(double(i) * theta_per_segment); + size_t n_arc_correction = N_ARC_CORRECTION; + + for (size_t i = 1; i < segments; ++i) { + if (n_arc_correction-- == 0) { + // Calculate the actual position for r_axis_x and r_axis_y + const double cos_Ti = ::cos((double)i * theta_per_segment); + const double sin_Ti = ::sin((double)i * theta_per_segment); curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti; curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti; - count = 0; + // reset n_arc_correction + n_arc_correction = N_ARC_CORRECTION; + } + else { + // Calculate X and Y using the small angle approximation + const float r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T; + curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T; + curr_rel_arc_start.y() = r_axisi; } // Update arc_target location diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index bf5443b03..7f82f21b0 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2322,7 +2322,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) if (move.type == EMoveType::Extrude) { #if ENABLE_PROCESS_G2_G3_LINES - if (move.extrusion_role != erNone && !move.internal_only) { + if (!move.internal_only) { #endif // ENABLE_PROCESS_G2_G3_LINES // layers zs const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();