diff --git a/src/libslic3r/Extruder.cpp b/src/libslic3r/Extruder.cpp index ea5a3b803b..af5af88cd8 100644 --- a/src/libslic3r/Extruder.cpp +++ b/src/libslic3r/Extruder.cpp @@ -16,6 +16,7 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config) : std::pair Extruder::extrude(double dE) { + assert(! std::isnan(dE)); // in case of relative E distances we always reset to 0 before any output if (m_config->use_relative_e_distances) m_E = 0.; @@ -37,7 +38,8 @@ std::pair Extruder::extrude(double dE) value supplied will overwrite the previous one if any. */ std::pair Extruder::retract(double retract_length, double restart_extra) { - assert(restart_extra >= 0); + assert(! std::isnan(retract_length)); + assert(! std::isnan(restart_extra) && restart_extra >= 0); // in case of relative E distances we always reset to 0 before any output if (m_config->use_relative_e_distances) m_E = 0.; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 231cba7c1b..ab625a7d90 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3105,27 +3105,35 @@ std::string GCodeGenerator::_extrude( auto end = path.end(); const bool emit_radius = m_config.arc_fitting == ArcFittingType::EmitRadius; for (++ it; it != end; ++ it) { - Vec2d p = this->point_to_gcode_quantized(it->point); - if (it->radius == 0) { + Vec2d p = this->point_to_gcode_quantized(it->point); + // Center of the radius to be emitted into the G-code: Either by radius or by center offset. + double radius = 0; + Vec2d ij; + if (it->radius != 0) { + // Extrude an arc. + assert(m_config.arc_fitting == ArcFittingType::EmitCenter || + m_config.arc_fitting == ArcFittingType::EmitRadius); + radius = unscaled(it->radius); + if (emit_radius) { + // Only quantize radius if emitting it directly into G-code. Otherwise use the exact radius for calculating the IJ values. + radius = GCodeFormatter::quantize_xyzf(radius); + } else { + // Calculate quantized IJ circle center offset. + ij = GCodeFormatter::quantize( + Geometry::ArcWelder::arc_center(prev.cast(), p.cast(), double(radius), it->ccw()) + - prev); + if (ij == Vec2d::Zero()) + // Don't extrude a degenerated circle. + radius = 0; + } + } + if (radius == 0) { // Extrude line segment. if (const double line_length = (p - prev).norm(); line_length > 0) { path_length += line_length; gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment); } } else { - // Extrude an arc. - assert(m_config.arc_fitting == ArcFittingType::EmitCenter || - m_config.arc_fitting == ArcFittingType::EmitRadius); - double radius = unscaled(it->radius); - if (emit_radius) - // Only quantize radius if emitting it directly into G-code. Otherwise use the exact radius for calculating the IJ values. - radius = GCodeFormatter::quantize_xyzf(radius); - Vec2d ij; - if (! emit_radius) { - // Calculate quantized IJ circle center offset. - Vec2d center_raw = Geometry::ArcWelder::arc_center(prev.cast(), p.cast(), double(radius), it->ccw()) - prev; - ij = GCodeFormatter::quantize(center_raw); - } double angle = Geometry::ArcWelder::arc_angle(prev.cast(), p.cast(), double(radius)); assert(angle > 0); const double line_length = angle * std::abs(radius); diff --git a/src/libslic3r/GCode/Wipe.cpp b/src/libslic3r/GCode/Wipe.cpp index 0fa887810f..fa726424e9 100644 --- a/src/libslic3r/GCode/Wipe.cpp +++ b/src/libslic3r/GCode/Wipe.cpp @@ -117,7 +117,7 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange) return done; }; const bool emit_radius = gcodegen.config().arc_fitting == ArcFittingType::EmitRadius; - auto wipe_arc = [&gcode, &gcodegen, &retract_length, xy_to_e, emit_radius]( + auto wipe_arc = [&gcode, &gcodegen, &retract_length, xy_to_e, emit_radius, &wipe_linear]( const Vec2d &prev_quantized, Vec2d &p, double radius_in, const bool ccw) { Vec2d p_quantized = GCodeFormatter::quantize(p); if (p_quantized == prev_quantized) { @@ -126,6 +126,9 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange) } // Only quantize radius if emitting it directly into G-code. Otherwise use the exact radius for calculating the IJ values. double radius = emit_radius ? GCodeFormatter::quantize_xyzf(radius_in) : radius_in; + if (radius == 0) + // Degenerated arc after quantization. Process it as if it was a line segment. + return wipe_linear(prev_quantized, p); Vec2d center = Geometry::ArcWelder::arc_center(prev_quantized.cast(), p_quantized.cast(), double(radius), ccw); float angle = Geometry::ArcWelder::arc_angle(prev_quantized.cast(), p_quantized.cast(), double(radius)); assert(angle > 0); @@ -152,8 +155,13 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange) gcode += gcodegen.writer().extrude_to_xy_G2G3R(p, radius, ccw, -dE, wipe_retract_comment); } else { // Calculate quantized IJ circle center offset. + Vec2d ij = GCodeFormatter::quantize(Vec2d(center - prev_quantized)); + if (ij == Vec2d::Zero()) + // Degenerated arc after quantization. Process it as if it was a line segment. + return wipe_linear(prev_quantized, p); + // The arc is valid. gcode += gcodegen.writer().extrude_to_xy_G2G3IJ( - p, GCodeFormatter::quantize(Vec2d(center - prev_quantized)), ccw, -dE, wipe_retract_comment); + p, ij, ccw, -dE, wipe_retract_comment); } retract_length -= dE; return done; diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index a9ecdb98ab..6e81aa21ac 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -1643,6 +1643,7 @@ namespace client // Check whether the table X values are sorted. double x = expr_x.as_d(); + assert(! std::isnan(x)); bool evaluated = false; for (size_t i = 1; i < table.table.size(); ++i) { double x0 = table.table[i - 1].x;