Skip to content

Commit 6234271

Browse files
committed
issue-7932: add option to repeat last layer while reducing extrusion to get a flush last layer in vase mode closes #7932
1 parent 3711402 commit 6234271

File tree

8 files changed

+116
-48
lines changed

8 files changed

+116
-48
lines changed

src/libslic3r/GCode.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1578,11 +1578,16 @@ void GCode::process_layers(
15781578
}
15791579
});
15801580
const auto spiral_vase = tbb::make_filter<LayerResult, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
1581-
[spiral_vase = this->m_spiral_vase.get()](LayerResult in) -> LayerResult {
1581+
[spiral_vase = this->m_spiral_vase.get(), &layers_to_print](LayerResult in) -> LayerResult {
15821582
if (in.nop_layer_result)
15831583
return in;
15841584

15851585
spiral_vase->enable(in.spiral_vase_enable);
1586+
1587+
if (in.layer_id == layers_to_print.size() - 1) {
1588+
spiral_vase->setLastLayer();
1589+
}
1590+
15861591
return { spiral_vase->process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush};
15871592
});
15881593
const auto pressure_equalizer = tbb::make_filter<LayerResult, LayerResult>(slic3r_tbb_filtermode::serial_in_order,

src/libslic3r/GCode/SpiralVase.cpp

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,52 +21,59 @@ std::string SpiralVase::process_layer(const std::string &gcode)
2121
at the beginning
2222
- each layer is composed by suitable geometry (i.e. a single complete loop)
2323
- loops were not clipped before calling this method */
24-
24+
2525
// If we're not going to modify G-code, just feed it to the reader
2626
// in order to update positions.
27-
if (! m_enabled) {
27+
if (!m_enabled) {
2828
m_reader.parse_buffer(gcode);
2929
return gcode;
3030
}
31-
31+
3232
// Get total XY length for this layer by summing all extrusion moves.
3333
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+
3737
{
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
5562
}
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+
6067
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.
6269
// For absolute extruder distances it will be switched off.
6370
// Tapering the absolute extruder distances requires to process every extrusion value after the first transition
6471
// 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;
6673
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) {
7077
if (line.cmd_is("G1")) {
7178
if (line.has_z()) {
7279
// 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)
8794
new_gcode += line.raw() + '\n';
8895
}
8996
return;
90-
97+
9198
/* Skip travel moves: the move to first perimeter point will
9299
cause a visible seam when loops are not aligned in XY; by skipping
93100
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)
98105
}
99106
new_gcode += line.raw() + '\n';
100107
});
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+
102147
return new_gcode;
103148
}
104149

105-
}
150+
} // namespace Slic3r

src/libslic3r/GCode/SpiralVase.hpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,36 @@
1414

1515
namespace Slic3r {
1616

17-
class SpiralVase {
17+
class SpiralVase
18+
{
1819
public:
1920
SpiralVase(const PrintConfig &config) : m_config(config)
2021
{
21-
m_reader.z() = (float)m_config.z_offset;
22+
m_reader.z() = (float) m_config.z_offset;
2223
m_reader.apply_config(m_config);
2324
};
2425

25-
void enable(bool en) {
26-
m_transition_layer = en && ! m_enabled;
27-
m_enabled = en;
26+
void enable(bool en)
27+
{
28+
m_transition_layer = en && !m_enabled;
29+
m_enabled = en;
2830
}
2931

32+
void setLastLayer() { m_last_layer = true; }
33+
3034
std::string process_layer(const std::string &gcode);
31-
35+
3236
private:
33-
const PrintConfig &m_config;
34-
GCodeReader m_reader;
37+
const PrintConfig &m_config;
38+
GCodeReader m_reader;
3539

36-
bool m_enabled = false;
40+
bool m_enabled = false;
3741
// First spiral vase layer. Layer height has to be ramped up from zero to the target layer height.
38-
bool m_transition_layer = false;
42+
bool m_transition_layer = false;
43+
// Last spiral vase layer. Repeat last layer on final height while reducing extrusion till zero.
44+
bool m_last_layer = false;
3945
};
4046

41-
}
47+
} // namespace Slic3r
4248

4349
#endif // slic3r_SpiralVase_hpp_

src/libslic3r/Preset.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
433433
}
434434

435435
static std::vector<std::string> s_Preset_print_options {
436-
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
436+
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "spiral_vase_flush_finish", "slice_closing_radius", "slicing_mode",
437437
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
438438
"extra_perimeters", "extra_perimeters_on_overhangs", "avoid_crossing_curled_overhangs", "avoid_crossing_perimeters", "thin_walls", "overhangs",
439439
"seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",

src/libslic3r/PrintConfig.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,13 @@ void PrintConfigDef::init_fff_params()
25322532
"It won't work when printing more than one single object.");
25332533
def->set_default_value(new ConfigOptionBool(false));
25342534

2535+
def = this->add("spiral_vase_flush_finish", coBool);
2536+
def->label = L("Spiral vase flush finish");
2537+
def->tooltip = L("End a spiral vase mode print with a flush layer. "
2538+
"Disable to restore the old behavior, which will end the print with a normal "
2539+
"vase mode layer - i.e. a slightly tilted layer.");
2540+
def->set_default_value(new ConfigOptionBool(true));
2541+
25352542
def = this->add("standby_temperature_delta", coInt);
25362543
def->label = L("Temperature variation");
25372544
// TRN PrintSettings : "Ooze prevention" > "Temperature variation"

src/libslic3r/PrintConfig.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
840840
((ConfigOptionInts, slowdown_below_layer_time))
841841
((ConfigOptionFloat, solid_infill_acceleration))
842842
((ConfigOptionBool, spiral_vase))
843+
((ConfigOptionBool, spiral_vase_flush_finish))
843844
((ConfigOptionInt, standby_temperature_delta))
844845
((ConfigOptionInts, temperature))
845846
((ConfigOptionInt, threads))

src/slic3r/GUI/ConfigManipulation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
237237
toggle_field("infill_anchor", has_infill_anchors);
238238

239239
bool has_spiral_vase = config->opt_bool("spiral_vase");
240+
bool have_spiral_vase_flush_finish = config->opt_bool("spiral_vase_flush_finish");
241+
toggle_field("spiral_vase_flush_finish", has_spiral_vase);
242+
240243
bool has_top_solid_infill = config->opt_int("top_solid_layers") > 0;
241244
bool has_bottom_solid_infill = config->opt_int("bottom_solid_layers") > 0;
242245
bool has_solid_infill = has_top_solid_infill || has_bottom_solid_infill;

src/slic3r/GUI/Tab.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,7 @@ void TabPrint::build()
14291429
optgroup = page->new_optgroup(L("Vertical shells"));
14301430
optgroup->append_single_option_line("perimeters", category_path + "perimeters");
14311431
optgroup->append_single_option_line("spiral_vase", category_path + "spiral-vase");
1432+
optgroup->append_single_option_line("spiral_vase_flush_finish");
14321433

14331434
Line line { "", "" };
14341435
line.full_width = 1;

0 commit comments

Comments
 (0)