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

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2018-01-03 19:29:49 +0300
committerbubnikv <bubnikv@gmail.com>2018-01-03 19:29:49 +0300
commitb292554fd84e95db9c19fb9f8df56b50cbaec9b5 (patch)
treeff264500eb377fd552eb6b8ebf3fe0731fe58ed0 /xs/src/libslic3r
parent0e4ecfaf56ffe276340a4f9ab7f963eee1c56d7b (diff)
Optimized the GCodeReader.
Fixed the profiling build.
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r--xs/src/libslic3r/GCode.cpp55
-rw-r--r--xs/src/libslic3r/GCode.hpp3
-rw-r--r--xs/src/libslic3r/GCode/SpiralVase.cpp47
-rw-r--r--xs/src/libslic3r/GCode/SpiralVase.hpp2
-rw-r--r--xs/src/libslic3r/GCodeReader.cpp221
-rw-r--r--xs/src/libslic3r/GCodeReader.hpp122
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.cpp147
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.hpp3
-rw-r--r--xs/src/libslic3r/libslic3r.h2
9 files changed, 390 insertions, 212 deletions
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 47bd6bc07..f713015f7 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -20,6 +20,8 @@
#include "SVG.hpp"
+#include <Shiny/Shiny.h>
+
#if 0
// Enable debugging and asserts, even in the release build.
#define DEBUG
@@ -348,6 +350,8 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
void GCode::do_export(Print *print, const char *path)
{
+ PROFILE_CLEAR();
+
// Remove the old g-code if it exists.
boost::nowide::remove(path);
@@ -384,10 +388,16 @@ void GCode::do_export(Print *print, const char *path)
throw std::runtime_error(
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
"Is " + path_tmp + " locked?" + '\n');
+
+ // Write the profiler measurements to file
+ PROFILE_UPDATE();
+ PROFILE_OUTPUT(debug_out_path("gcode-export-profile.txt").c_str());
}
void GCode::_do_export(Print &print, FILE *file)
{
+ PROFILE_FUNC();
+
// resets time estimator
m_time_estimator.reset();
@@ -1987,44 +1997,41 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
return gcode;
}
-void GCode::_write(FILE* file, const std::string& what)
+void GCode::_write(FILE* file, const char *what, size_t size)
{
- if (!what.empty()) {
+ if (size > 0) {
// writes string to file
- fwrite(what.data(), 1, what.size(), file);
+ fwrite(what, 1, size, file);
// updates time estimator and gcode lines vector
- const char endLine = '\n';
- std::string::size_type beginPos = 0;
- std::string::size_type endPos = what.find_first_of(endLine, beginPos);
- while (endPos != std::string::npos) {
- std::string line = what.substr(beginPos, endPos - beginPos + 1);
- m_time_estimator.add_gcode_line(line);
- beginPos = endPos + 1;
- endPos = what.find_first_of(endLine, beginPos);
- }
+ m_time_estimator.add_gcode_block(what);
}
}
-void GCode::_writeln(FILE* file, const std::string& what)
+void GCode::_writeln(FILE* file, const std::string &what)
{
- if (!what.empty()) {
- if (what.back() != '\n')
- _write_format(file, "%s\n", what.c_str());
- else
- _write(file, what);
- }
+ if (! what.empty())
+ _write(file, (what.back() == '\n') ? what : (what + '\n'));
}
void GCode::_write_format(FILE* file, const char* format, ...)
{
- char buffer[1024];
va_list args;
va_start(args, format);
- int res = ::vsnprintf(buffer, 1024, format, args);
+ int buflen =
+#ifdef _MSC_VER
+ _vscprintf(format, args);
+#else
+ vsnprintf(nullptr, 0, format, args);
+#endif
+ char buffer[1024];
+ bool buffer_dynamic = buflen > 1024;
+ char *bufptr = buffer_dynamic ? (char*)malloc(buflen) : buffer;
+ int res = ::vsnprintf(bufptr, buflen, format, args);
+ if (res >= 0 && bufptr[0] != 0)
+ _write(file, bufptr, buflen);
va_end(args);
-
- if (res >= 0)
- _writeln(file, buffer);
+ if (buffer_dynamic)
+ free(bufptr);
}
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed)
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index cb8b0027a..5c622ec2d 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -278,7 +278,8 @@ protected:
GCodeTimeEstimator m_time_estimator;
// Write a string into a file.
- void _write(FILE* file, const std::string& what);
+ void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str(), what.size()); }
+ void _write(FILE* file, const char *what, size_t size);
// Write a string into a file.
// Add a newline, if the string does not end with a newline already.
diff --git a/xs/src/libslic3r/GCode/SpiralVase.cpp b/xs/src/libslic3r/GCode/SpiralVase.cpp
index fd300067f..892d3b4cc 100644
--- a/xs/src/libslic3r/GCode/SpiralVase.cpp
+++ b/xs/src/libslic3r/GCode/SpiralVase.cpp
@@ -4,17 +4,7 @@
namespace Slic3r {
-std::string
-_format_z(float z)
-{
- std::ostringstream ss;
- ss << std::fixed << std::setprecision(3)
- << z;
- return ss.str();
-}
-
-std::string
-SpiralVase::process_layer(const std::string &gcode)
+std::string SpiralVase::process_layer(const std::string &gcode)
{
/* This post-processor relies on several assumptions:
- all layers are processed through it, including those that are not supposed
@@ -38,16 +28,17 @@ SpiralVase::process_layer(const std::string &gcode)
bool set_z = false;
{
+ //FIXME Performance warning: This copies the GCodeConfig of the reader.
GCodeReader r = this->_reader; // clone
r.parse(gcode, [&total_layer_length, &layer_height, &z, &set_z]
- (GCodeReader &, const GCodeReader::GCodeLine &line) {
- if (line.cmd == "G1") {
- if (line.extruding()) {
- total_layer_length += line.dist_XY();
- } else if (line.has('Z')) {
- layer_height += line.dist_Z();
+ (GCodeReader &reader, const GCodeReader::GCodeLine &line) {
+ if (line.cmd_is("G1")) {
+ if (line.extruding(reader)) {
+ total_layer_length += line.dist_XY(reader);
+ } else if (line.has(Z)) {
+ layer_height += line.dist_Z(reader);
if (!set_z) {
- z = line.new_Z();
+ z = line.new_Z(reader);
set_z = true;
}
}
@@ -60,22 +51,22 @@ SpiralVase::process_layer(const std::string &gcode)
std::string new_gcode;
this->_reader.parse(gcode, [&new_gcode, &z, &layer_height, &total_layer_length]
- (GCodeReader &, GCodeReader::GCodeLine line) {
- if (line.cmd == "G1") {
- if (line.has('Z')) {
+ (GCodeReader &reader, GCodeReader::GCodeLine line) {
+ if (line.cmd_is("G1")) {
+ if (line.has_z()) {
// If this is the initial Z move of the layer, replace it with a
// (redundant) move to the last Z of previous layer.
- line.set('Z', _format_z(z));
- new_gcode += line.raw + '\n';
+ line.set(reader, Z, z);
+ new_gcode += line.raw() + '\n';
return;
} else {
- float dist_XY = line.dist_XY();
+ float dist_XY = line.dist_XY(reader);
if (dist_XY > 0) {
// horizontal move
- if (line.extruding()) {
+ if (line.extruding(reader)) {
z += dist_XY * layer_height / total_layer_length;
- line.set('Z', _format_z(z));
- new_gcode += line.raw + '\n';
+ line.set(reader, Z, z);
+ new_gcode += line.raw() + '\n';
}
return;
@@ -87,7 +78,7 @@ SpiralVase::process_layer(const std::string &gcode)
}
}
}
- new_gcode += line.raw + '\n';
+ new_gcode += line.raw() + '\n';
});
return new_gcode;
diff --git a/xs/src/libslic3r/GCode/SpiralVase.hpp b/xs/src/libslic3r/GCode/SpiralVase.hpp
index 234642524..60aa668d8 100644
--- a/xs/src/libslic3r/GCode/SpiralVase.hpp
+++ b/xs/src/libslic3r/GCode/SpiralVase.hpp
@@ -13,7 +13,7 @@ class SpiralVase {
SpiralVase(const PrintConfig &config)
: enable(false), _config(&config)
{
- this->_reader.Z = this->_config->z_offset;
+ this->_reader.z() = this->_config->z_offset;
this->_reader.apply_config(*this->_config);
};
std::string process_layer(const std::string &gcode);
diff --git a/xs/src/libslic3r/GCodeReader.cpp b/xs/src/libslic3r/GCodeReader.cpp
index 453cc9f94..86009fb0f 100644
--- a/xs/src/libslic3r/GCodeReader.cpp
+++ b/xs/src/libslic3r/GCodeReader.cpp
@@ -4,6 +4,8 @@
#include <fstream>
#include <iostream>
+#include <Shiny/Shiny.h>
+
namespace Slic3r {
void GCodeReader::apply_config(const GCodeConfig &config)
@@ -26,58 +28,121 @@ void GCodeReader::parse(const std::string &gcode, callback_t callback)
this->parse_line(line, callback);
}
-void GCodeReader::parse_line(std::string line, callback_t callback)
+static inline bool is_whitespace(char c)
{
- GCodeLine gline(this);
- gline.raw = line;
- if (this->verbose)
- std::cout << line << std::endl;
-
- // strip comment
- {
- size_t pos = line.find(';');
- if (pos != std::string::npos) {
- gline.comment = line.substr(pos+1);
- line.erase(pos);
- }
- }
+ return c == ' ' || c == '\t';
+}
+
+static inline bool is_end_of_line(char c)
+{
+ return c == '\r' || c == '\n' || c == 0;
+}
+
+static inline bool is_end_of_gcode_line(char c)
+{
+ return c == ';' || is_end_of_line(c);
+}
+
+static inline bool is_end_of_word(char c)
+{
+ return is_whitespace(c) || is_end_of_gcode_line(c);
+}
+
+static inline const char* skip_whitespaces(const char *c)
+{
+ for (; is_whitespace(*c); ++ c);
+ return c;
+}
+
+static inline const char* skip_word(const char *c)
+{
+ for (; ! is_end_of_word(*c); ++ c);
+ return c;
+}
+
+const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, std::pair<const char*, const char*> &command)
+{
+ PROFILE_FUNC();
// command and args
+ const char *c = ptr;
{
- std::vector<std::string> args;
- boost::split(args, line, boost::is_any_of(" "));
-
- // first one is cmd
- gline.cmd = args.front();
- args.erase(args.begin());
-
- for (std::string &arg : args) {
- if (arg.size() < 2) continue;
- gline.args.insert(std::make_pair(arg[0], arg.substr(1)));
+ PROFILE_BLOCK(command_and_args);
+ // Skip the whitespaces.
+ command.first = skip_whitespaces(c);
+ // Skip the command.
+ c = command.second = skip_word(command.first);
+ // Up to the end of line or comment.
+ while (! is_end_of_gcode_line(*c)) {
+ // Skip whitespaces.
+ c = skip_whitespaces(c);
+ if (is_end_of_gcode_line(*c))
+ break;
+ // Check the name of the axis.
+ Axis axis = NUM_AXES;
+ switch (*c) {
+ case 'X': axis = X; break;
+ case 'Y': axis = Y; break;
+ case 'Z': axis = Z; break;
+ case 'F': axis = F; break;
+ default:
+ if (*c == m_extrusion_axis)
+ axis = E;
+ break;
+ }
+ if (axis != NUM_AXES) {
+ // Try to parse the numeric value.
+ char *pend = nullptr;
+ double v = strtod(++ c, &pend);
+ if (pend != nullptr && is_end_of_word(*pend)) {
+ // The axis value has been parsed correctly.
+ gline.m_axis[int(axis)] = float(v);
+ gline.m_mask |= 1 << int(axis);
+ c = pend;
+ } else
+ // Skip the rest of the word.
+ c = skip_word(c);
+ } else
+ // Skip the rest of the word.
+ c = skip_word(c);
}
}
- // convert extrusion axis
- if (m_extrusion_axis != 'E') {
- const auto it = gline.args.find(m_extrusion_axis);
- if (it != gline.args.end()) {
- std::swap(gline.args['E'], it->second);
- gline.args.erase(it);
- }
+ if (gline.has(E) && m_config.use_relative_e_distances)
+ m_position[E] = 0;
+
+ // Skip the rest of the line.
+ for (; ! is_end_of_line(*c); ++ c);
+
+ // Copy the raw string including the comment, without the trailing newlines.
+ if (c > ptr) {
+ PROFILE_BLOCK(copy_raw_string);
+ gline.m_raw.assign(ptr, c);
}
-
- if (gline.has('E') && m_config.use_relative_e_distances)
- this->E = 0;
-
- if (callback) callback(*this, gline);
-
- // update coordinates
- if (gline.cmd == "G0" || gline.cmd == "G1" || gline.cmd == "G92") {
- this->X = gline.new_X();
- this->Y = gline.new_Y();
- this->Z = gline.new_Z();
- this->E = gline.new_E();
- this->F = gline.new_F();
+
+ // Skip the trailing newlines.
+ if (*c == '\r')
+ ++ c;
+ if (*c == '\n')
+ ++ c;
+
+ if (m_verbose)
+ std::cout << gline.m_raw << std::endl;
+
+ return c;
+}
+
+void GCodeReader::update_coordinates(GCodeLine &gline, std::pair<const char*, const char*> &command)
+{
+ PROFILE_FUNC();
+ if (*command.first == 'G') {
+ int cmd_len = int(command.second - command.first);
+ if ((cmd_len == 2 && (command.first[1] == '0' || command.first[1] == '1')) ||
+ (cmd_len == 3 && command.first[1] == '9' && command.first[2] == '2')) {
+ for (size_t i = 0; i < NUM_AXES; ++ i)
+ if (gline.has(Axis(i)))
+ this->m_position[i] = gline.value(Axis(i));
+ }
}
}
@@ -89,22 +154,64 @@ void GCodeReader::parse_file(const std::string &file, callback_t callback)
this->parse_line(line, callback);
}
-void GCodeReader::GCodeLine::set(char arg, std::string value)
+bool GCodeReader::GCodeLine::has_value(char axis, float &value) const
{
- const std::string space(" ");
- if (this->has(arg)) {
- size_t pos = this->raw.find(space + arg)+2;
- size_t end = this->raw.find(' ', pos+1);
- this->raw = this->raw.replace(pos, end-pos, value);
- } else {
- size_t pos = this->raw.find(' ');
- if (pos == std::string::npos) {
- this->raw += space + arg + value;
- } else {
- this->raw = this->raw.replace(pos, 0, space + arg + value);
+ const char *c = m_raw.c_str();
+ // Skip the whitespaces.
+ c = skip_whitespaces(c);
+ // Skip the command.
+ c = skip_word(c);
+ // Up to the end of line or comment.
+ while (! is_end_of_gcode_line(*c)) {
+ // Skip whitespaces.
+ c = skip_whitespaces(c);
+ if (is_end_of_gcode_line(*c))
+ break;
+ // Check the name of the axis.
+ if (*c == axis) {
+ // Try to parse the numeric value.
+ char *pend = nullptr;
+ double v = strtod(++ c, &pend);
+ if (pend != nullptr && is_end_of_word(*pend)) {
+ // The axis value has been parsed correctly.
+ value = float(v);
+ return true;
+ }
}
+ // Skip the rest of the word.
+ c = skip_word(c);
+ }
+ return false;
+}
+
+void GCodeReader::GCodeLine::set(const GCodeReader &reader, const Axis axis, const float new_value, const int decimal_digits)
+{
+ std::ostringstream ss;
+ ss << std::fixed << std::setprecision(decimal_digits) << new_value;
+
+ char match[3] = " X";
+ if (int(axis) < 3)
+ match[1] += int(axis);
+ else if (axis == F)
+ match[1] = 'F';
+ else {
+ assert(axis == E);
+ match[1] = reader.extrusion_axis();
+ }
+
+ if (this->has(axis)) {
+ size_t pos = m_raw.find(match)+2;
+ size_t end = m_raw.find(' ', pos+1);
+ m_raw = m_raw.replace(pos, end-pos, ss.str());
+ } else {
+ size_t pos = m_raw.find(' ');
+ if (pos == std::string::npos)
+ m_raw += std::string(match) + ss.str();
+ else
+ m_raw = m_raw.replace(pos, 0, std::string(match) + ss.str());
}
- this->args[arg] = value;
+ m_axis[axis] = new_value;
+ m_mask |= 1 << int(axis);
}
}
diff --git a/xs/src/libslic3r/GCodeReader.hpp b/xs/src/libslic3r/GCodeReader.hpp
index 1792d6cde..4a7825520 100644
--- a/xs/src/libslic3r/GCodeReader.hpp
+++ b/xs/src/libslic3r/GCodeReader.hpp
@@ -11,54 +11,104 @@
namespace Slic3r {
class GCodeReader {
-public:
+public:
class GCodeLine {
public:
- GCodeReader* reader;
- std::string raw;
- std::string cmd;
- std::string comment;
- std::map<char,std::string> args;
-
- GCodeLine(GCodeReader* _reader) : reader(_reader) {};
-
- bool has(char arg) const { return this->args.count(arg) > 0; };
- float get_float(char arg) const { return float(atof(this->args.at(arg).c_str())); };
- float new_X() const { return this->has('X') ? float(atof(this->args.at('X').c_str())) : this->reader->X; };
- float new_Y() const { return this->has('Y') ? float(atof(this->args.at('Y').c_str())) : this->reader->Y; };
- float new_Z() const { return this->has('Z') ? float(atof(this->args.at('Z').c_str())) : this->reader->Z; };
- float new_E() const { return this->has('E') ? float(atof(this->args.at('E').c_str())) : this->reader->E; };
- float new_F() const { return this->has('F') ? float(atof(this->args.at('F').c_str())) : this->reader->F; };
- float dist_X() const { return this->new_X() - this->reader->X; };
- float dist_Y() const { return this->new_Y() - this->reader->Y; };
- float dist_Z() const { return this->new_Z() - this->reader->Z; };
- float dist_E() const { return this->new_E() - this->reader->E; };
- float dist_XY() const {
- float x = this->dist_X();
- float y = this->dist_Y();
+ GCodeLine() { reset(); }
+ void reset() { m_mask = 0; memset(m_axis, 0, sizeof(m_axis)); m_raw.clear(); }
+
+ const std::string& raw() const { return m_raw; }
+ const std::string cmd() const
+ { size_t pos = m_raw.find_first_of(" \t\n;"); return (pos == std::string::npos) ? m_raw : m_raw.substr(0, pos); }
+ const std::string comment() const
+ { size_t pos = m_raw.find(';'); return (pos == std::string::npos) ? "" : m_raw.substr(pos + 1); }
+
+ bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; }
+ float value(Axis axis) const { return m_axis[axis]; }
+ bool has_value(char axis, float &value) const;
+ float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
+ float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
+ float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }
+ float dist_X(const GCodeReader &reader) const { return this->has(X) ? (this->x() - reader.x()) : 0; }
+ float dist_Y(const GCodeReader &reader) const { return this->has(Y) ? (this->y() - reader.y()) : 0; }
+ float dist_Z(const GCodeReader &reader) const { return this->has(Z) ? (this->z() - reader.z()) : 0; }
+ float dist_E(const GCodeReader &reader) const { return this->has(E) ? (this->e() - reader.e()) : 0; }
+ float dist_XY(const GCodeReader &reader) const {
+ float x = this->has(X) ? (this->x() - reader.x()) : 0;
+ float y = this->has(Y) ? (this->y() - reader.y()) : 0;
return sqrt(x*x + y*y);
- };
- bool extruding() const { return this->cmd == "G1" && this->dist_E() > 0; };
- bool retracting() const { return this->cmd == "G1" && this->dist_E() < 0; };
- bool travel() const { return this->cmd == "G1" && ! this->has('E'); };
- void set(char arg, std::string value);
+ }
+ bool cmd_is(const char *cmd_test) const {
+ int len = strlen(cmd_test);
+ if (strncmp(m_raw.c_str(), cmd_test, len))
+ return false;
+ char c = m_raw.c_str()[len];
+ return c == 0 || c == ' ' || c == '\t' || c == ';';
+ }
+ bool extruding(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) > 0; }
+ bool retracting(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) < 0; }
+ bool travel() const { return this->cmd_is("G1") && ! this->has(E); }
+ void set(const GCodeReader &reader, const Axis axis, const float new_value, const int decimal_digits = 3);
+
+ bool has_x() const { return this->has(X); }
+ bool has_y() const { return this->has(Y); }
+ bool has_z() const { return this->has(Z); }
+ bool has_e() const { return this->has(E); }
+ bool has_f() const { return this->has(F); }
+ float x() const { return m_axis[X]; }
+ float y() const { return m_axis[Y]; }
+ float z() const { return m_axis[Z]; }
+ float e() const { return m_axis[E]; }
+ float f() const { return m_axis[F]; }
+
+ private:
+ std::string m_raw;
+ float m_axis[NUM_AXES];
+ uint32_t m_mask;
+ friend class GCodeReader;
};
+
typedef std::function<void(GCodeReader&, const GCodeLine&)> callback_t;
- float X, Y, Z, E, F;
- bool verbose;
- callback_t callback;
-
- GCodeReader() : X(0), Y(0), Z(0), E(0), F(0), verbose(false), m_extrusion_axis('E') {};
+ GCodeReader() : m_verbose(false), m_extrusion_axis('E') { memset(m_position, 0, sizeof(m_position)); }
void apply_config(const GCodeConfig &config);
void apply_config(const DynamicPrintConfig &config);
void parse(const std::string &gcode, callback_t callback);
- void parse_line(std::string line, callback_t callback);
+ template<typename Callback>
+ const char* parse_line(const char *ptr, GCodeLine &gline, Callback &callback)
+ {
+ std::pair<const char*, const char*> cmd;
+ const char *end = parse_line_internal(ptr, gline, cmd);
+ callback(*this, gline);
+ update_coordinates(gline, cmd);
+ return end;
+ }
+ template<typename Callback>
+ void parse_line(const std::string &line, Callback &callback)
+ { GCodeLine gline; this->parse_line(line.c_str(), gline, callback); }
void parse_file(const std::string &file, callback_t callback);
-
+
+ float& x() { return m_position[X]; }
+ float x() const { return m_position[X]; }
+ float& y() { return m_position[Y]; }
+ float y() const { return m_position[Y]; }
+ float& z() { return m_position[Z]; }
+ float z() const { return m_position[Z]; }
+ float& e() { return m_position[E]; }
+ float e() const { return m_position[E]; }
+ float& f() { return m_position[F]; }
+ float f() const { return m_position[F]; }
+
+ char extrusion_axis() const { return m_extrusion_axis; }
+
private:
+ const char* parse_line_internal(const char *ptr, GCodeLine &gline, std::pair<const char*, const char*> &command);
+ void update_coordinates(GCodeLine &gline, std::pair<const char*, const char*> &command);
+
GCodeConfig m_config;
- char m_extrusion_axis;
+ char m_extrusion_axis;
+ float m_position[NUM_AXES];
+ bool m_verbose;
};
} /* namespace Slic3r */
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp
index 43b331676..31ee30cc1 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp
@@ -4,7 +4,6 @@
#include <Shiny/Shiny.h>
-static const std::string AXIS_STR = "XYZE";
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float MILLISEC_TO_SEC = 0.001f;
static const float INCHES_TO_MM = 25.4f;
@@ -159,7 +158,9 @@ namespace Slic3r {
{
for (const std::string& line : gcode_lines)
{
- _parser.parse_line(line, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
+ _parser.parse_line(line,
+ [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); });
}
_calculate_time();
reset();
@@ -168,7 +169,21 @@ namespace Slic3r {
void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
{
PROFILE_FUNC();
- _parser.parse_line(gcode_line, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
+ _parser.parse_line(gcode_line,
+ [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); });
+ }
+
+ void GCodeTimeEstimator::add_gcode_block(const char *ptr)
+ {
+ PROFILE_FUNC();
+ GCodeReader::GCodeLine gline;
+ for (; *ptr != 0;) {
+ gline.reset();
+ ptr = _parser.parse_line(ptr, gline,
+ [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); });
+ }
}
void GCodeTimeEstimator::calculate_time()
@@ -406,13 +421,14 @@ namespace Slic3r {
void GCodeTimeEstimator::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
{
PROFILE_FUNC();
- if (line.cmd.length() > 1)
+ std::string cmd = line.cmd();
+ if (cmd.length() > 1)
{
- switch (::toupper(line.cmd[0]))
+ switch (::toupper(cmd[0]))
{
case 'G':
{
- switch (::atoi(&line.cmd[1]))
+ switch (::atoi(&cmd[1]))
{
case 1: // Move
{
@@ -460,7 +476,7 @@ namespace Slic3r {
}
case 'M':
{
- switch (::atoi(&line.cmd[1]))
+ switch (::atoi(&cmd[1]))
{
case 82: // Set extruder to absolute mode
{
@@ -514,9 +530,9 @@ namespace Slic3r {
float axis_absolute_position_from_G1_line(GCodeTimeEstimator::EAxis axis, const GCodeReader::GCodeLine& lineG1, GCodeTimeEstimator::EUnits units, GCodeTimeEstimator::EPositioningType type, float current_absolute_position)
{
float lengthsScaleFactor = (units == GCodeTimeEstimator::Inches) ? INCHES_TO_MM : 1.0f;
- if (lineG1.has(AXIS_STR[axis]))
+ if (lineG1.has(Slic3r::Axis(axis)))
{
- float ret = lineG1.get_float(AXIS_STR[axis]) * lengthsScaleFactor;
+ float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
return (type == GCodeTimeEstimator::Absolute) ? ret : current_absolute_position + ret;
}
else
@@ -534,8 +550,8 @@ namespace Slic3r {
}
// updates feedrate from line, if present
- if (line.has('F'))
- set_feedrate(std::max(line.get_float('F') * MMMIN_TO_MMSEC, get_minimum_feedrate()));
+ if (line.has_f())
+ set_feedrate(std::max(line.f() * MMMIN_TO_MMSEC, get_minimum_feedrate()));
// fills block data
Block block;
@@ -682,15 +698,16 @@ namespace Slic3r {
}
// adds block to blocks list
- _blocks.push_back(block);
+ _blocks.emplace_back(block);
}
void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line)
{
EDialect dialect = get_dialect();
- if (line.has('P'))
- add_additional_time(line.get_float('P') * MILLISEC_TO_SEC);
+ float value;
+ if (line.has_value('P', value))
+ add_additional_time(value * MILLISEC_TO_SEC);
// see: http://reprap.org/wiki/G-code#G4:_Dwell
if ((dialect == Repetier) ||
@@ -698,8 +715,8 @@ namespace Slic3r {
(dialect == Smoothieware) ||
(dialect == RepRapFirmware))
{
- if (line.has('S'))
- add_additional_time(line.get_float('S'));
+ if (line.has_value('S', value))
+ add_additional_time(value);
}
}
@@ -745,27 +762,27 @@ namespace Slic3r {
float lengthsScaleFactor = (get_units() == Inches) ? INCHES_TO_MM : 1.0f;
bool anyFound = false;
- if (line.has('X'))
+ if (line.has_x())
{
- set_axis_position(X, line.get_float('X') * lengthsScaleFactor);
+ set_axis_position(X, line.x() * lengthsScaleFactor);
anyFound = true;
}
- if (line.has('Y'))
+ if (line.has_y())
{
- set_axis_position(Y, line.get_float('Y') * lengthsScaleFactor);
+ set_axis_position(Y, line.y() * lengthsScaleFactor);
anyFound = true;
}
- if (line.has('Z'))
+ if (line.has_z())
{
- set_axis_position(Z, line.get_float('Z') * lengthsScaleFactor);
+ set_axis_position(Z, line.z() * lengthsScaleFactor);
anyFound = true;
}
- if (line.has('E'))
+ if (line.has_e())
{
- set_axis_position(E, line.get_float('E') * lengthsScaleFactor);
+ set_axis_position(E, line.e() * lengthsScaleFactor);
anyFound = true;
}
@@ -790,17 +807,17 @@ namespace Slic3r {
// see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration
float factor = ((dialect != RepRapFirmware) && (get_units() == GCodeTimeEstimator::Inches)) ? INCHES_TO_MM : 1.0f;
- if (line.has('X'))
- set_axis_max_acceleration(X, line.get_float('X') * factor);
+ if (line.has_x())
+ set_axis_max_acceleration(X, line.x() * factor);
- if (line.has('Y'))
- set_axis_max_acceleration(Y, line.get_float('Y') * factor);
+ if (line.has_y())
+ set_axis_max_acceleration(Y, line.y() * factor);
- if (line.has('Z'))
- set_axis_max_acceleration(Z, line.get_float('Z') * factor);
+ if (line.has_z())
+ set_axis_max_acceleration(Z, line.z() * factor);
- if (line.has('E'))
- set_axis_max_acceleration(E, line.get_float('E') * factor);
+ if (line.has_e())
+ set_axis_max_acceleration(E, line.e() * factor);
}
void GCodeTimeEstimator::_processM203(const GCodeReader::GCodeLine& line)
@@ -814,66 +831,68 @@ namespace Slic3r {
// see http://reprap.org/wiki/G-code#M203:_Set_maximum_feedrate
float factor = (dialect == Marlin) ? 1.0f : MMMIN_TO_MMSEC;
- if (line.has('X'))
- set_axis_max_feedrate(X, line.get_float('X') * factor);
+ if (line.has_x())
+ set_axis_max_feedrate(X, line.x() * factor);
- if (line.has('Y'))
- set_axis_max_feedrate(Y, line.get_float('Y') * factor);
+ if (line.has_y())
+ set_axis_max_feedrate(Y, line.y() * factor);
- if (line.has('Z'))
- set_axis_max_feedrate(Z, line.get_float('Z') * factor);
+ if (line.has_z())
+ set_axis_max_feedrate(Z, line.z() * factor);
- if (line.has('E'))
- set_axis_max_feedrate(E, line.get_float('E') * factor);
+ if (line.has_e())
+ set_axis_max_feedrate(E, line.e() * factor);
}
void GCodeTimeEstimator::_processM204(const GCodeReader::GCodeLine& line)
{
- if (line.has('S'))
- set_acceleration(line.get_float('S'));
+ float value;
+ if (line.has_value('S', value))
+ set_acceleration(value);
- if (line.has('T'))
- set_retract_acceleration(line.get_float('T'));
+ if (line.has_value('T', value))
+ set_retract_acceleration(value);
}
void GCodeTimeEstimator::_processM205(const GCodeReader::GCodeLine& line)
{
- if (line.has('X'))
+ if (line.has_x())
{
- float max_jerk = line.get_float('X');
+ float max_jerk = line.x();
set_axis_max_jerk(X, max_jerk);
set_axis_max_jerk(Y, max_jerk);
}
- if (line.has('Y'))
- set_axis_max_jerk(Y, line.get_float('Y'));
+ if (line.has_y())
+ set_axis_max_jerk(Y, line.y());
- if (line.has('Z'))
- set_axis_max_jerk(Z, line.get_float('Z'));
+ if (line.has_z())
+ set_axis_max_jerk(Z, line.z());
- if (line.has('E'))
- set_axis_max_jerk(E, line.get_float('E'));
+ if (line.has_e())
+ set_axis_max_jerk(E, line.e());
- if (line.has('S'))
- set_minimum_feedrate(line.get_float('S'));
+ float value;
+ if (line.has_value('S', value))
+ set_minimum_feedrate(value);
- if (line.has('T'))
- set_minimum_travel_feedrate(line.get_float('T'));
+ if (line.has_value('T', value))
+ set_minimum_travel_feedrate(value);
}
void GCodeTimeEstimator::_processM566(const GCodeReader::GCodeLine& line)
{
- if (line.has('X'))
- set_axis_max_jerk(X, line.get_float('X') * MMMIN_TO_MMSEC);
+ if (line.has_x())
+ set_axis_max_jerk(X, line.x() * MMMIN_TO_MMSEC);
- if (line.has('Y'))
- set_axis_max_jerk(Y, line.get_float('Y') * MMMIN_TO_MMSEC);
+ if (line.has_y())
+ set_axis_max_jerk(Y, line.y() * MMMIN_TO_MMSEC);
- if (line.has('Z'))
- set_axis_max_jerk(Z, line.get_float('Z') * MMMIN_TO_MMSEC);
+ if (line.has_z())
+ set_axis_max_jerk(Z, line.z() * MMMIN_TO_MMSEC);
- if (line.has('E'))
- set_axis_max_jerk(E, line.get_float('E') * MMMIN_TO_MMSEC);
+ if (line.has_e())
+ set_axis_max_jerk(E, line.e() * MMMIN_TO_MMSEC);
}
void GCodeTimeEstimator::_forward_pass()
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp
index 894d00ef3..84c6de5fc 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp
@@ -183,6 +183,9 @@ namespace Slic3r {
// Adds the given gcode line
void add_gcode_line(const std::string& gcode_line);
+ void add_gcode_block(const char *ptr);
+ void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
+
// Calculates the time estimate from the gcode lines added using add_gcode_line()
void calculate_time();
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 1a02605e1..7c694b05e 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -102,7 +102,7 @@ inline std::string debug_out_path(const char *name, ...)
namespace Slic3r {
-enum Axis { X=0, Y, Z };
+enum Axis { X=0, Y, Z, E, F, NUM_AXES };
template <class T>
inline void append_to(std::vector<T> &dst, const std::vector<T> &src)