@@ -21,52 +21,59 @@ std::string SpiralVase::process_layer(const std::string &gcode)
21
21
at the beginning
22
22
- each layer is composed by suitable geometry (i.e. a single complete loop)
23
23
- loops were not clipped before calling this method */
24
-
24
+
25
25
// If we're not going to modify G-code, just feed it to the reader
26
26
// in order to update positions.
27
- if (! m_enabled) {
27
+ if (!m_enabled) {
28
28
m_reader.parse_buffer (gcode);
29
29
return gcode;
30
30
}
31
-
31
+
32
32
// Get total XY length for this layer by summing all extrusion moves.
33
33
float total_layer_length = 0 ;
34
- float layer_height = 0 ;
35
- float z = 0 .f ;
36
-
34
+ float layer_height = 0 ;
35
+ float layer_z = 0 .f ;
36
+
37
37
{
38
- // FIXME Performance warning: This copies the GCodeConfig of the reader.
39
- GCodeReader r = m_reader; // clone
40
- bool set_z = false ;
41
- r.parse_buffer (gcode, [&total_layer_length, &layer_height, &z, &set_z]
42
- (GCodeReader &reader, const GCodeReader::GCodeLine &line) {
43
- if (line.cmd_is (" G1" )) {
44
- if (line.extruding (reader)) {
45
- total_layer_length += line.dist_XY (reader);
46
- } else if (line.has (Z)) {
47
- layer_height += line.dist_Z (reader);
48
- if (!set_z) {
49
- z = line.new_Z (reader);
50
- set_z = true ;
51
- }
52
- }
53
- }
54
- });
38
+ // FIXME Performance warning: This copies the GCodeConfig of the reader.
39
+ GCodeReader r = m_reader; // clone
40
+ bool set_z = false ;
41
+ r.parse_buffer (gcode,
42
+ [&total_layer_length, &layer_height, &layer_z, &set_z](GCodeReader &reader, const GCodeReader::GCodeLine &line) {
43
+ if (line.cmd_is (" G1" )) {
44
+ if (line.extruding (reader)) {
45
+ total_layer_length += line.dist_XY (reader);
46
+ } else if (line.has (Z)) {
47
+ layer_height += line.dist_Z (reader);
48
+ if (!set_z) {
49
+ layer_z = line.new_Z (reader);
50
+ set_z = true ;
51
+ }
52
+ }
53
+ }
54
+ });
55
+ }
56
+
57
+ // get a copy of the reader in case a last_layer_transition should be done
58
+ bool last_layer_transition = m_config.spiral_vase_flush_finish && m_last_layer && m_config.use_relative_e_distances .value ;
59
+ GCodeReader last_layer_reader;
60
+ if (last_layer_transition) {
61
+ last_layer_reader = m_reader; // clone
55
62
}
56
-
57
- // Remove layer height from initial Z.
58
- z -= layer_height;
59
-
63
+
64
+ // Remove layer height from initial Z.
65
+ float z = layer_z - layer_height;
66
+
60
67
std::string new_gcode;
61
- // FIXME Tapering of the transition layer only works reliably with relative extruder distances.
68
+ // FIXME Tapering of the transition layer only works reliably with relative extruder distances.
62
69
// For absolute extruder distances it will be switched off.
63
70
// Tapering the absolute extruder distances requires to process every extrusion value after the first transition
64
71
// layer.
65
- bool transition = m_transition_layer && m_config.use_relative_e_distances .value ;
72
+ bool transition = m_transition_layer && m_config.use_relative_e_distances .value ;
66
73
float layer_height_factor = layer_height / total_layer_length;
67
- float len = 0 .f ;
68
- m_reader.parse_buffer (gcode, [&new_gcode, &z, total_layer_length, layer_height_factor, transition, &len]
69
- (GCodeReader &reader, GCodeReader::GCodeLine line) {
74
+ float len = 0 .f ;
75
+ m_reader.parse_buffer (gcode, [&new_gcode, &z, total_layer_length, layer_height_factor, transition, &len](GCodeReader &reader,
76
+ GCodeReader::GCodeLine line) {
70
77
if (line.cmd_is (" G1" )) {
71
78
if (line.has_z ()) {
72
79
// If this is the initial Z move of the layer, replace it with a
@@ -87,7 +94,7 @@ std::string SpiralVase::process_layer(const std::string &gcode)
87
94
new_gcode += line.raw () + ' \n ' ;
88
95
}
89
96
return ;
90
-
97
+
91
98
/* Skip travel moves: the move to first perimeter point will
92
99
cause a visible seam when loops are not aligned in XY; by skipping
93
100
it we blend the first loop move in the XY plane (although the smoothness
@@ -98,8 +105,46 @@ std::string SpiralVase::process_layer(const std::string &gcode)
98
105
}
99
106
new_gcode += line.raw () + ' \n ' ;
100
107
});
101
-
108
+
109
+ if (last_layer_transition) {
110
+ // Repeat last layer on final height while reducing extrusion to zero to get a flush last layer.
111
+ len = 0 .f ;
112
+
113
+ last_layer_reader.parse_buffer (gcode, [&new_gcode, &layer_z, total_layer_length, layer_height_factor, transition,
114
+ last_layer_transition, &len](GCodeReader &reader, GCodeReader::GCodeLine line) {
115
+ if (line.cmd_is (" G1" )) {
116
+ if (line.has_z ()) {
117
+ // Set z to final layer_z.
118
+ // We should actually already be at this height.
119
+ line.set (reader, Z, layer_z);
120
+ new_gcode += line.raw () + ' \n ' ;
121
+ return ;
122
+ } else {
123
+ float dist_XY = line.dist_XY (reader);
124
+ if (dist_XY > 0 ) {
125
+ if (line.extruding (reader)) {
126
+ len += dist_XY;
127
+ if (line.has (E))
128
+ // Transition layer, modulate the amount of extrusion to zero.
129
+ line.set (reader, E, line.value (E) * (1 .f - len / total_layer_length));
130
+ new_gcode += line.raw () + ' \n ' ;
131
+ }
132
+ return ;
133
+ }
134
+ }
135
+ }
136
+
137
+ // We need to remove the layer change comment before the last_layer_transition,
138
+ // as otherwise the gcode preview will not work properly. The transition layer will be part of the last layer.
139
+ // Note: we need to keep the other layer change commands though - e.g. resetting the relative E value.
140
+ if (last_layer_transition && line.comment () == GCodeProcessor::reserved_tag (GCodeProcessor::ETags::Layer_Change)) {
141
+ return ;
142
+ }
143
+ new_gcode += line.raw () + ' \n ' ;
144
+ });
145
+ }
146
+
102
147
return new_gcode;
103
148
}
104
149
105
- }
150
+ } // namespace Slic3r
0 commit comments