Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2021-09-13 12:55:38 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-09-13 12:55:44 +0300
commite7591e6aa60042c19a0aa20305af0f6e0d8439c0 (patch)
treefeaee7b5468f863d8916ddbe940da88b328b6e75 /src/libslic3r
parentfda8ef6fce84b1371c1737f8adb82ed937f45c39 (diff)
GCodeWriter: published GCodeFormatter, made it more generic, so
it could be used outside of GCodeWriter. Ported the GCodeWriter::retract/deretract to GCodeFormatter.
Diffstat (limited to 'src/libslic3r')
-rw-r--r--src/libslic3r/GCodeWriter.cpp223
-rw-r--r--src/libslic3r/GCodeWriter.hpp74
2 files changed, 150 insertions, 147 deletions
diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp
index eb45e95c1..83557fdbb 100644
--- a/src/libslic3r/GCodeWriter.cpp
+++ b/src/libslic3r/GCodeWriter.cpp
@@ -1,7 +1,6 @@
#include "GCodeWriter.hpp"
#include "CustomGCode.hpp"
#include <algorithm>
-#include <charconv>
#include <iomanip>
#include <iostream>
#include <map>
@@ -11,15 +10,8 @@
#include <boost/spirit/include/karma.hpp>
#endif
-#define XYZF_EXPORT_DIGITS 3
-#define E_EXPORT_DIGITS 5
-
#define FLAVOR_IS(val) this->config.gcode_flavor == val
#define FLAVOR_IS_NOT(val) this->config.gcode_flavor != val
-#define COMMENT(comment) if (this->config.gcode_comments && !comment.empty()) gcode << " ; " << comment;
-#define PRECISION(val, precision) std::fixed << std::setprecision(precision) << (val)
-#define XYZF_NUM(val) PRECISION(val, XYZF_EXPORT_DIGITS)
-#define E_NUM(val) PRECISION(val, E_EXPORT_DIGITS)
namespace Slic3r {
@@ -261,115 +253,12 @@ std::string GCodeWriter::toolchange(unsigned int extruder_id)
return gcode.str();
}
-class G1Writer {
-private:
- static constexpr const size_t buflen = 256;
- char buf[buflen];
- char *buf_end;
- std::to_chars_result ptr_err;
-
-public:
- G1Writer() {
- this->buf[0] = 'G';
- this->buf[1] = '1';
- this->buf_end = this->buf + buflen;
- this->ptr_err.ptr = this->buf + 2;
- }
-
- void emit_axis(const char axis, const double v, size_t digits) {
- assert(digits <= 6);
- static constexpr const std::array<int, 7> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000};
- *ptr_err.ptr++ = ' '; *ptr_err.ptr++ = axis;
-
- char *base_ptr = this->ptr_err.ptr;
- auto v_int = int64_t(std::round(v * pow_10[digits]));
- // Older stdlib on macOS doesn't support std::from_chars at all, so it is used boost::spirit::karma::generate instead of it.
- // That is a little bit slower than std::to_chars but not much.
-#ifdef __APPLE__
- boost::spirit::karma::generate(this->ptr_err.ptr, boost::spirit::karma::int_generator<int64_t>(), v_int);
-#else
- // this->buf_end minus 1 because we need space for adding the extra decimal point.
- this->ptr_err = std::to_chars(this->ptr_err.ptr, this->buf_end - 1, v_int);
-#endif
- size_t writen_digits = (this->ptr_err.ptr - base_ptr) - (v_int < 0 ? 1 : 0);
- if (writen_digits < digits) {
- // Number is smaller than 10^digits, so that we will pad it with zeros.
- size_t remaining_digits = digits - writen_digits;
- // Move all newly inserted chars by remaining_digits to allocate space for padding with zeros.
- for (char *from_ptr = this->ptr_err.ptr - 1, *to_ptr = from_ptr + remaining_digits; from_ptr >= this->ptr_err.ptr - writen_digits; --to_ptr, --from_ptr)
- *to_ptr = *from_ptr;
-
- memset(this->ptr_err.ptr - writen_digits, '0', remaining_digits);
- this->ptr_err.ptr += remaining_digits;
- }
-
- // Move all newly inserted chars by one to allocate space for a decimal point.
- for (char *to_ptr = this->ptr_err.ptr, *from_ptr = to_ptr - 1; from_ptr >= this->ptr_err.ptr - digits; --to_ptr, --from_ptr)
- *to_ptr = *from_ptr;
-
- *(this->ptr_err.ptr - digits) = '.';
- for (size_t i = 0; i < digits; ++i) {
- if (*this->ptr_err.ptr != '0')
- break;
- this->ptr_err.ptr--;
- }
- if (*this->ptr_err.ptr == '.')
- this->ptr_err.ptr--;
- if ((this->ptr_err.ptr + 1) == base_ptr || *this->ptr_err.ptr == '-')
- *(++this->ptr_err.ptr) = '0';
- this->ptr_err.ptr++;
- }
-
- void emit_xy(const Vec2d &point) {
- this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS);
- this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS);
- }
-
- void emit_xyz(const Vec3d &point) {
- this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS);
- this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS);
- this->emit_z(point.z());
- }
-
- void emit_z(const double z) {
- this->emit_axis('Z', z, XYZF_EXPORT_DIGITS);
- }
-
- void emit_e(const std::string &axis, double v) {
- if (! axis.empty()) {
- // not gcfNoExtrusion
- this->emit_axis(axis[0], v, E_EXPORT_DIGITS);
- }
- }
-
- void emit_f(double speed) {
- this->emit_axis('F', speed, XYZF_EXPORT_DIGITS);
- }
-
- void emit_string(const std::string &s) {
- strncpy(ptr_err.ptr, s.c_str(), s.size());
- ptr_err.ptr += s.size();
- }
-
- void emit_comment(bool allow_comments, const std::string &comment) {
- if (allow_comments && ! comment.empty()) {
- *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = ';'; *ptr_err.ptr ++ = ' ';
- this->emit_string(comment);
- }
- }
-
- std::string string() {
- *ptr_err.ptr ++ = '\n';
- return std::string(this->buf, ptr_err.ptr - buf);
- }
-};
-
std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker) const
{
assert(F > 0.);
assert(F < 100000.);
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_f(F);
w.emit_comment(this->config.gcode_comments, comment);
w.emit_string(cooling_marker);
@@ -381,7 +270,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
m_pos(0) = point(0);
m_pos(1) = point(1);
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_xy(point);
w.emit_f(this->config.travel_speed.value * 60.0);
w.emit_comment(this->config.gcode_comments, comment);
@@ -414,7 +303,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
m_lifted = 0;
m_pos = point;
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_xyz(point);
w.emit_f(this->config.travel_speed.value * 60.0);
w.emit_comment(this->config.gcode_comments, comment);
@@ -448,7 +337,7 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
if (speed == 0.)
speed = this->config.travel_speed.value;
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_z(z);
w.emit_f(speed * 60.0);
w.emit_comment(this->config.gcode_comments, comment);
@@ -473,7 +362,7 @@ std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std:
m_pos(1) = point(1);
m_extruder->extrude(dE);
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_xy(point);
w.emit_e(m_extrusion_axis, m_extruder->E());
w.emit_comment(this->config.gcode_comments, comment);
@@ -486,7 +375,7 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
m_lifted = 0;
m_extruder->extrude(dE);
- G1Writer w;
+ auto w = GCodeFormatter::G1();
w.emit_xyz(point);
w.emit_e(m_extrusion_axis, m_extruder->E());
w.emit_comment(this->config.gcode_comments, comment);
@@ -517,12 +406,11 @@ std::string GCodeWriter::retract_for_toolchange(bool before_wipe)
std::string GCodeWriter::_retract(double length, double restart_extra, const std::string &comment)
{
- std::ostringstream gcode;
-
/* If firmware retraction is enabled, we use a fake value of 1
since we ignore the actual configured retract_length which
might be 0, in which case the retraction logic gets skipped. */
- if (this->config.use_firmware_retraction) length = 1;
+ if (this->config.use_firmware_retraction)
+ length = 1;
// If we use volumetric E values we turn lengths into volumes */
if (this->config.use_volumetric_e) {
@@ -532,52 +420,48 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
restart_extra = restart_extra * area;
}
- double dE = m_extruder->retract(length, restart_extra);
- if (dE != 0) {
+
+ std::string gcode;
+ if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
if (this->config.use_firmware_retraction) {
- if (FLAVOR_IS(gcfMachinekit))
- gcode << "G22 ; retract\n";
- else
- gcode << "G10 ; retract\n";
+ gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
} else if (! m_extrusion_axis.empty()) {
- gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E())
- << " F" << XYZF_NUM(m_extruder->retract_speed() * 60.);
- COMMENT(comment);
- gcode << "\n";
+ auto w = GCodeFormatter::G1();
+ w.emit_e(m_extrusion_axis, m_extruder->E());
+ w.emit_f(m_extruder->retract_speed() * 60.);
+ w.emit_comment(this->config.gcode_comments, comment);
+ gcode = w.string();
}
}
if (FLAVOR_IS(gcfMakerWare))
- gcode << "M103 ; extruder off\n";
-
- return gcode.str();
+ gcode += "M103 ; extruder off\n";
+
+ return gcode;
}
std::string GCodeWriter::unretract()
{
- std::ostringstream gcode;
+ std::string gcode;
if (FLAVOR_IS(gcfMakerWare))
- gcode << "M101 ; extruder on\n";
+ gcode = "M101 ; extruder on\n";
- double dE = m_extruder->unretract();
- if (dE != 0) {
+ if (double dE = m_extruder->unretract(); dE != 0) {
if (this->config.use_firmware_retraction) {
- if (FLAVOR_IS(gcfMachinekit))
- gcode << "G23 ; unretract\n";
- else
- gcode << "G11 ; unretract\n";
- gcode << this->reset_e();
+ gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
+ gcode += this->reset_e();
} else if (! m_extrusion_axis.empty()) {
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
- gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E())
- << " F" << XYZF_NUM(m_extruder->deretract_speed() * 60.);
- if (this->config.gcode_comments) gcode << " ; unretract";
- gcode << "\n";
+ auto w = GCodeFormatter::G1();
+ w.emit_e(m_extrusion_axis, m_extruder->E());
+ w.emit_f(m_extruder->deretract_speed() * 60.);
+ w.emit_comment(this->config.gcode_comments, " ; unretract");
+ gcode += w.string();
}
}
- return gcode.str();
+ return gcode;
}
/* If this method is called more than once before calling unlift(),
@@ -649,4 +533,49 @@ std::string GCodeWriter::set_fan(unsigned int speed) const
return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed);
}
+
+void GCodeFormatter::emit_axis(const char axis, const double v, size_t digits) {
+ assert(digits <= 6);
+ static constexpr const std::array<int, 7> pow_10{1, 10, 100, 1000, 10000, 100000, 1000000};
+ *ptr_err.ptr++ = ' '; *ptr_err.ptr++ = axis;
+
+ char *base_ptr = this->ptr_err.ptr;
+ auto v_int = int64_t(std::round(v * pow_10[digits]));
+ // Older stdlib on macOS doesn't support std::from_chars at all, so it is used boost::spirit::karma::generate instead of it.
+ // That is a little bit slower than std::to_chars but not much.
+#ifdef __APPLE__
+ boost::spirit::karma::generate(this->ptr_err.ptr, boost::spirit::karma::int_generator<int64_t>(), v_int);
+#else
+ // this->buf_end minus 1 because we need space for adding the extra decimal point.
+ this->ptr_err = std::to_chars(this->ptr_err.ptr, this->buf_end - 1, v_int);
+#endif
+ size_t writen_digits = (this->ptr_err.ptr - base_ptr) - (v_int < 0 ? 1 : 0);
+ if (writen_digits < digits) {
+ // Number is smaller than 10^digits, so that we will pad it with zeros.
+ size_t remaining_digits = digits - writen_digits;
+ // Move all newly inserted chars by remaining_digits to allocate space for padding with zeros.
+ for (char *from_ptr = this->ptr_err.ptr - 1, *to_ptr = from_ptr + remaining_digits; from_ptr >= this->ptr_err.ptr - writen_digits; --to_ptr, --from_ptr)
+ *to_ptr = *from_ptr;
+
+ memset(this->ptr_err.ptr - writen_digits, '0', remaining_digits);
+ this->ptr_err.ptr += remaining_digits;
+ }
+
+ // Move all newly inserted chars by one to allocate space for a decimal point.
+ for (char *to_ptr = this->ptr_err.ptr, *from_ptr = to_ptr - 1; from_ptr >= this->ptr_err.ptr - digits; --to_ptr, --from_ptr)
+ *to_ptr = *from_ptr;
+
+ *(this->ptr_err.ptr - digits) = '.';
+ for (size_t i = 0; i < digits; ++i) {
+ if (*this->ptr_err.ptr != '0')
+ break;
+ this->ptr_err.ptr--;
+ }
+ if (*this->ptr_err.ptr == '.')
+ this->ptr_err.ptr--;
+ if ((this->ptr_err.ptr + 1) == base_ptr || *this->ptr_err.ptr == '-')
+ *(++this->ptr_err.ptr) = '0';
+ this->ptr_err.ptr++;
}
+
+} // namespace Slic3r
diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp
index dd602ca80..12a2b5a88 100644
--- a/src/libslic3r/GCodeWriter.hpp
+++ b/src/libslic3r/GCodeWriter.hpp
@@ -3,6 +3,7 @@
#include "libslic3r.h"
#include <string>
+#include <charconv>
#include "Extruder.hpp"
#include "Point.hpp"
#include "PrintConfig.hpp"
@@ -93,6 +94,79 @@ private:
std::string _retract(double length, double restart_extra, const std::string &comment);
};
+class GCodeFormatter {
+private:
+ static constexpr const size_t buflen = 256;
+ char buf[buflen];
+ char *buf_end;
+ std::to_chars_result ptr_err;
+
+ GCodeFormatter() {
+ this->buf_end = buf + buflen;
+ this->ptr_err.ptr = this->buf;
+ }
+
+public:
+ static constexpr const int XYZF_EXPORT_DIGITS = 3;
+ static constexpr const int E_EXPORT_DIGITS = 5;
+
+ static GCodeFormatter empty() {
+ return {};
+ }
+ static GCodeFormatter G1() {
+ GCodeFormatter out;
+ out.buf[0] = 'G';
+ out.buf[1] = '1';
+ out.ptr_err.ptr += 2;
+ return out;
+ }
+
+ void emit_axis(const char axis, const double v, size_t digits);
+
+ void emit_xy(const Vec2d &point) {
+ this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS);
+ this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS);
+ }
+
+ void emit_xyz(const Vec3d &point) {
+ this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS);
+ this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS);
+ this->emit_z(point.z());
+ }
+
+ void emit_z(const double z) {
+ this->emit_axis('Z', z, XYZF_EXPORT_DIGITS);
+ }
+
+ void emit_e(const std::string &axis, double v) {
+ if (! axis.empty()) {
+ // not gcfNoExtrusion
+ this->emit_axis(axis[0], v, E_EXPORT_DIGITS);
+ }
+ }
+
+ void emit_f(double speed) {
+ this->emit_axis('F', speed, XYZF_EXPORT_DIGITS);
+ }
+
+ void emit_string(const std::string &s) {
+ strncpy(ptr_err.ptr, s.c_str(), s.size());
+ ptr_err.ptr += s.size();
+ }
+
+ void emit_comment(bool allow_comments, const std::string &comment) {
+ if (allow_comments && ! comment.empty()) {
+ *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = ';'; *ptr_err.ptr ++ = ' ';
+ this->emit_string(comment);
+ }
+ }
+
+ std::string string() {
+ *ptr_err.ptr ++ = '\n';
+ return std::string(this->buf, ptr_err.ptr - buf);
+ }
+};
+
} /* namespace Slic3r */
#endif /* slic3r_GCodeWriter_hpp_ */