diff options
Diffstat (limited to 'src/libslic3r/GCode/SpiralVase.cpp')
-rw-r--r-- | src/libslic3r/GCode/SpiralVase.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/libslic3r/GCode/SpiralVase.cpp b/src/libslic3r/GCode/SpiralVase.cpp new file mode 100644 index 000000000..8e8ae3075 --- /dev/null +++ b/src/libslic3r/GCode/SpiralVase.cpp @@ -0,0 +1,87 @@ +#include "SpiralVase.hpp" +#include "GCode.hpp" +#include <sstream> + +namespace Slic3r { + +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 + to be transformed, in order to update the reader with the XY positions + - each call to this method includes a full layer, with a single Z move + at the beginning + - each layer is composed by suitable geometry (i.e. a single complete loop) + - loops were not clipped before calling this method */ + + // If we're not going to modify G-code, just feed it to the reader + // in order to update positions. + if (!this->enable) { + this->_reader.parse_buffer(gcode); + return gcode; + } + + // Get total XY length for this layer by summing all extrusion moves. + float total_layer_length = 0; + float layer_height = 0; + float z; + bool set_z = false; + + { + //FIXME Performance warning: This copies the GCodeConfig of the reader. + GCodeReader r = this->_reader; // clone + r.parse_buffer(gcode, [&total_layer_length, &layer_height, &z, &set_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(reader); + set_z = true; + } + } + } + }); + } + + // Remove layer height from initial Z. + z -= layer_height; + + std::string new_gcode; + this->_reader.parse_buffer(gcode, [&new_gcode, &z, &layer_height, &total_layer_length] + (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(reader, Z, z); + new_gcode += line.raw() + '\n'; + return; + } else { + float dist_XY = line.dist_XY(reader); + if (dist_XY > 0) { + // horizontal move + if (line.extruding(reader)) { + z += dist_XY * layer_height / total_layer_length; + line.set(reader, Z, z); + new_gcode += line.raw() + '\n'; + } + return; + + /* Skip travel moves: the move to first perimeter point will + cause a visible seam when loops are not aligned in XY; by skipping + it we blend the first loop move in the XY plane (although the smoothness + of such blend depend on how long the first segment is; maybe we should + enforce some minimum length?). */ + } + } + } + new_gcode += line.raw() + '\n'; + }); + + return new_gcode; +} + +} |