2017-04-26 12:24:31 +00:00
|
|
|
|
#include "SpiralVase.hpp"
|
2017-05-03 16:28:22 +00:00
|
|
|
|
#include "GCode.hpp"
|
2017-04-26 12:24:31 +00:00
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
2018-01-03 16:29:49 +00:00
|
|
|
|
std::string SpiralVase::process_layer(const std::string &gcode)
|
2017-04-26 12:24:31 +00:00
|
|
|
|
{
|
|
|
|
|
/* 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(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;
|
|
|
|
|
|
|
|
|
|
{
|
2018-01-03 16:29:49 +00:00
|
|
|
|
//FIXME Performance warning: This copies the GCodeConfig of the reader.
|
2017-04-26 12:24:31 +00:00
|
|
|
|
GCodeReader r = this->_reader; // clone
|
|
|
|
|
r.parse(gcode, [&total_layer_length, &layer_height, &z, &set_z]
|
2018-01-03 16:29:49 +00:00
|
|
|
|
(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);
|
2017-04-26 12:24:31 +00:00
|
|
|
|
if (!set_z) {
|
2018-01-03 16:29:49 +00:00
|
|
|
|
z = line.new_Z(reader);
|
2017-04-26 12:24:31 +00:00
|
|
|
|
set_z = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove layer height from initial Z.
|
|
|
|
|
z -= layer_height;
|
|
|
|
|
|
|
|
|
|
std::string new_gcode;
|
|
|
|
|
this->_reader.parse(gcode, [&new_gcode, &z, &layer_height, &total_layer_length]
|
2018-01-03 16:29:49 +00:00
|
|
|
|
(GCodeReader &reader, GCodeReader::GCodeLine line) {
|
|
|
|
|
if (line.cmd_is("G1")) {
|
|
|
|
|
if (line.has_z()) {
|
2017-04-26 12:24:31 +00:00
|
|
|
|
// If this is the initial Z move of the layer, replace it with a
|
|
|
|
|
// (redundant) move to the last Z of previous layer.
|
2018-01-03 16:29:49 +00:00
|
|
|
|
line.set(reader, Z, z);
|
|
|
|
|
new_gcode += line.raw() + '\n';
|
2017-04-26 12:24:31 +00:00
|
|
|
|
return;
|
|
|
|
|
} else {
|
2018-01-03 16:29:49 +00:00
|
|
|
|
float dist_XY = line.dist_XY(reader);
|
2017-04-26 12:24:31 +00:00
|
|
|
|
if (dist_XY > 0) {
|
|
|
|
|
// horizontal move
|
2018-01-03 16:29:49 +00:00
|
|
|
|
if (line.extruding(reader)) {
|
2017-04-26 12:24:31 +00:00
|
|
|
|
z += dist_XY * layer_height / total_layer_length;
|
2018-01-03 16:29:49 +00:00
|
|
|
|
line.set(reader, Z, z);
|
|
|
|
|
new_gcode += line.raw() + '\n';
|
2017-04-26 12:24:31 +00:00
|
|
|
|
}
|
|
|
|
|
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?). */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-03 16:29:49 +00:00
|
|
|
|
new_gcode += line.raw() + '\n';
|
2017-04-26 12:24:31 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return new_gcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|