mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:32:01 +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)
|
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
|
// in case of relative E distances we always reset to 0 before any output
|
||||||
if (m_config->use_relative_e_distances)
|
if (m_config->use_relative_e_distances)
|
||||||
m_E = 0.;
|
m_E = 0.;
|
||||||
@ -37,7 +38,8 @@ std::pair<double, double> Extruder::extrude(double dE)
|
|||||||
value supplied will overwrite the previous one if any. */
|
value supplied will overwrite the previous one if any. */
|
||||||
std::pair<double, double> Extruder::retract(double retract_length, double restart_extra)
|
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
|
// in case of relative E distances we always reset to 0 before any output
|
||||||
if (m_config->use_relative_e_distances)
|
if (m_config->use_relative_e_distances)
|
||||||
m_E = 0.;
|
m_E = 0.;
|
||||||
|
@ -3105,27 +3105,35 @@ std::string GCodeGenerator::_extrude(
|
|||||||
auto end = path.end();
|
auto end = path.end();
|
||||||
const bool emit_radius = m_config.arc_fitting == ArcFittingType::EmitRadius;
|
const bool emit_radius = m_config.arc_fitting == ArcFittingType::EmitRadius;
|
||||||
for (++ it; it != end; ++ it) {
|
for (++ it; it != end; ++ it) {
|
||||||
Vec2d p = this->point_to_gcode_quantized(it->point);
|
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.
|
// Extrude line segment.
|
||||||
if (const double line_length = (p - prev).norm(); line_length > 0) {
|
if (const double line_length = (p - prev).norm(); line_length > 0) {
|
||||||
path_length += line_length;
|
path_length += line_length;
|
||||||
gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment);
|
gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment);
|
||||||
}
|
}
|
||||||
} else {
|
} 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));
|
double angle = Geometry::ArcWelder::arc_angle(prev.cast<double>(), p.cast<double>(), double(radius));
|
||||||
assert(angle > 0);
|
assert(angle > 0);
|
||||||
const double line_length = angle * std::abs(radius);
|
const double line_length = angle * std::abs(radius);
|
||||||
|
@ -117,7 +117,7 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange)
|
|||||||
return done;
|
return done;
|
||||||
};
|
};
|
||||||
const bool emit_radius = gcodegen.config().arc_fitting == ArcFittingType::EmitRadius;
|
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) {
|
const Vec2d &prev_quantized, Vec2d &p, double radius_in, const bool ccw) {
|
||||||
Vec2d p_quantized = GCodeFormatter::quantize(p);
|
Vec2d p_quantized = GCodeFormatter::quantize(p);
|
||||||
if (p_quantized == prev_quantized) {
|
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.
|
// 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;
|
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);
|
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));
|
float angle = Geometry::ArcWelder::arc_angle(prev_quantized.cast<double>(), p_quantized.cast<double>(), double(radius));
|
||||||
assert(angle > 0);
|
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);
|
gcode += gcodegen.writer().extrude_to_xy_G2G3R(p, radius, ccw, -dE, wipe_retract_comment);
|
||||||
} else {
|
} else {
|
||||||
// Calculate quantized IJ circle center offset.
|
// 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(
|
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;
|
retract_length -= dE;
|
||||||
return done;
|
return done;
|
||||||
|
@ -1643,6 +1643,7 @@ namespace client
|
|||||||
|
|
||||||
// Check whether the table X values are sorted.
|
// Check whether the table X values are sorted.
|
||||||
double x = expr_x.as_d();
|
double x = expr_x.as_d();
|
||||||
|
assert(! std::isnan(x));
|
||||||
bool evaluated = false;
|
bool evaluated = false;
|
||||||
for (size_t i = 1; i < table.table.size(); ++i) {
|
for (size_t i = 1; i < table.table.size(); ++i) {
|
||||||
double x0 = table.table[i - 1].x;
|
double x0 = table.table[i - 1].x;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user