mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:42:00 +08:00
ArcWelder: Fixed NaN when exporting arches with nearly zero radii.
This commit is contained in:
parent
b39c33414f
commit
4580e69d86
@ -16,6 +16,7 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config) :
|
||||
|
||||
std::pair<double, double> 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<double, double> Extruder::extrude(double dE)
|
||||
value supplied will overwrite the previous one if any. */
|
||||
std::pair<double, double> 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.;
|
||||
|
@ -3106,26 +3106,34 @@ std::string GCodeGenerator::_extrude(
|
||||
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) {
|
||||
// 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<double>(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<double>(), p.cast<double>(), 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<double>(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<double>(), p.cast<double>(), double(radius), it->ccw()) - prev;
|
||||
ij = GCodeFormatter::quantize(center_raw);
|
||||
}
|
||||
double angle = Geometry::ArcWelder::arc_angle(prev.cast<double>(), p.cast<double>(), double(radius));
|
||||
assert(angle > 0);
|
||||
const double line_length = angle * std::abs(radius);
|
||||
|
@ -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<double>(), p_quantized.cast<double>(), double(radius), ccw);
|
||||
float angle = Geometry::ArcWelder::arc_angle(prev_quantized.cast<double>(), p_quantized.cast<double>(), 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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user