/
SpiralVase.cpp
95 lines (84 loc) · 3.22 KB
/
SpiralVase.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "SpiralVase.hpp"
#include <sstream>
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)
{
/* 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;
{
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();
if (!set_z) {
z = line.new_Z();
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]
(GCodeReader &, GCodeReader::GCodeLine line) {
if (line.cmd == "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';
return;
} else {
float dist_XY = line.dist_XY();
if (dist_XY > 0) {
// horizontal move
if (line.extruding()) {
z += dist_XY * layer_height / total_layer_length;
line.set('Z', _format_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;
}
}