Skip to content

Commit

Permalink
Fix milling post-process
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Sep 16, 2022
1 parent 0981595 commit 3466946
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 105 deletions.
60 changes: 30 additions & 30 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2054,14 +2054,14 @@ void GCode::process_layers(

// The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress();
if (m_spiral_vase && m_find_replace)
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & fan_mover & find_replace & output);
else if (m_spiral_vase)
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & fan_mover & output);
else if (m_find_replace)
tbb::parallel_pipeline(12, generator & cooling & fan_mover & find_replace & output);
else
tbb::parallel_pipeline(12, generator & cooling & fan_mover & output);
tbb::filter<void, GCode::LayerResult> pipeline_to_layerresult = generator;
if (m_spiral_vase)
pipeline_to_layerresult = pipeline_to_layerresult & spiral_vase;
tbb::filter<void, std::string> pipeline_to_string = pipeline_to_layerresult & cooling & fan_mover;
if (m_find_replace)
pipeline_to_string = pipeline_to_string & find_replace;
tbb::filter<void, void> full_pipeline = pipeline_to_string & output;
tbb::parallel_pipeline(12, full_pipeline);
output_stream.find_replace_enable();
}

Expand Down Expand Up @@ -2091,9 +2091,9 @@ void GCode::process_layers(
});
const auto spiral_vase = tbb::make_filter<GCode::LayerResult, GCode::LayerResult>(slic3r_tbb_filtermode::serial_in_order,
[&spiral_vase = *this->m_spiral_vase.get()](GCode::LayerResult in)->GCode::LayerResult {
spiral_vase.enable(in.spiral_vase_enable);
return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush };
});
spiral_vase.enable(in.spiral_vase_enable);
return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush };
});
const auto cooling = tbb::make_filter<GCode::LayerResult, std::string>(slic3r_tbb_filtermode::serial_in_order,
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string {
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
Expand Down Expand Up @@ -2128,14 +2128,14 @@ void GCode::process_layers(

// The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress();
if (m_spiral_vase && m_find_replace)
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & fan_mover & find_replace & output);
else if (m_spiral_vase)
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & fan_mover & output);
else if (m_find_replace)
tbb::parallel_pipeline(12, generator & cooling & fan_mover & find_replace & output);
else
tbb::parallel_pipeline(12, generator & cooling & fan_mover & output);
tbb::filter<void, GCode::LayerResult> pipeline_to_layerresult = generator;
if (m_spiral_vase)
pipeline_to_layerresult = pipeline_to_layerresult & spiral_vase;
tbb::filter<void, std::string> pipeline_to_string = pipeline_to_layerresult & cooling & fan_mover;
if (m_find_replace)
pipeline_to_string = pipeline_to_string & find_replace;
tbb::filter<void, void> full_pipeline = pipeline_to_string & output;
tbb::parallel_pipeline(12, full_pipeline);
output_stream.find_replace_enable();
}

Expand Down Expand Up @@ -3162,14 +3162,6 @@ GCode::LayerResult GCode::process_layer(
}
}

#if 0
// Apply spiral vase post-processing if this layer contains suitable geometry
// (we must feed all the G-code into the post-processor, including the first
// bottom non-spiral layers otherwise it will mess with positions)
// we apply spiral vase at this stage because it requires a full layer.
// Just a reminder: A spiral vase mode is allowed for a single object per layer, single material print only.
if (m_spiral_vase)
gcode = m_spiral_vase->process_layer(std::move(gcode));


//add milling post-process if enabled
Expand Down Expand Up @@ -3210,10 +3202,10 @@ GCode::LayerResult GCode::process_layer(
check_add_eol(gcode);
}

gcode += "\n; began print:";
gcode += "\n; began milling:\n";
for (const LayerToPrint& ltp : layers) {
if (ltp.object_layer != nullptr) {
for (const PrintInstance& print_instance : ltp.object()->instances()){
for (const PrintInstance& print_instance : ltp.object()->instances()) {
this->set_origin(unscale(print_instance.shift));
for (const LayerRegion* lr : ltp.object_layer->regions()) {
if (!lr->milling.empty()) {
Expand All @@ -3227,7 +3219,7 @@ GCode::LayerResult GCode::process_layer(
}

//switch to extruder
m_placeholder_parser.set("current_extruder", milling_extruder_id);
m_placeholder_parser.set("current_extruder", current_extruder_filament);
// Append the filament start G-code.
const std::string& end_mill_gcode = m_config.milling_toolchange_end_gcode.get_at(0);
if (!end_mill_gcode.empty()) {
Expand All @@ -3250,6 +3242,14 @@ GCode::LayerResult GCode::process_layer(
}
}

#if 0
// Apply spiral vase post-processing if this layer contains suitable geometry
// (we must feed all the G-code into the post-processor, including the first
// bottom non-spiral layers otherwise it will mess with positions)
// we apply spiral vase at this stage because it requires a full layer.
// Just a reminder: A spiral vase mode is allowed for a single object per layer, single material print only.
if (m_spiral_vase)
gcode = m_spiral_vase->process_layer(std::move(gcode));

// Apply cooling logic; this may alter speeds.
if (m_cooling_buffer)
Expand Down
149 changes: 85 additions & 64 deletions src/libslic3r/GCode/SpiralVase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,29 @@ std::string SpiralVase::process_layer(const std::string &gcode)
//FIXME Performance warning: This copies the GCodeConfig of the reader.
GCodeReader r = m_reader; // clone
bool set_z = false;
r.parse_buffer(gcode, [&total_layer_length, &layer_height, &z, &set_z, &height_str]
bool milling = false;
r.parse_buffer(gcode, [&total_layer_length, &layer_height, &z, &set_z, &height_str, &milling]
(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;
if (boost::starts_with(line.comment(), " milling"))
milling = true;
if (!milling) {
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;
}
}
}
} else {
const std::string& comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
std::string comment_str = comment.substr(1);
if (boost::starts_with(comment_str, GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height))) {
height_str = comment_str.substr(GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).size());
} else {
const std::string& comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
std::string comment_str = comment.substr(1);
if (boost::starts_with(comment_str, GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height))) {
height_str = comment_str.substr(GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).size());
}
}
}
}
Expand Down Expand Up @@ -79,67 +84,83 @@ std::string SpiralVase::process_layer(const std::string &gcode)
float len = 0.f;
double E_accumulator = 0;
double last_old_E = 0;
m_reader.parse_buffer(gcode, [this, &keep_first_travel , &new_gcode, &z, total_layer_length, layer_height_factor, &len, &E_accumulator, &last_old_E, &height_str]
bool is_milling = false;
GCodeReader::GCodeLine line_last_position;
m_reader.parse_buffer(gcode, [this, &keep_first_travel , &new_gcode, &z, total_layer_length, layer_height_factor, &len, &E_accumulator, &last_old_E, &height_str, &is_milling, &line_last_position]
(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)) {
keep_first_travel = false;
len += dist_XY;
line.set(reader, Z, z + len * layer_height_factor);
if (m_transition_layer && line.has(E)) {
// Transition layer, modulate the amount of extrusion from zero to the final value.
if (m_config.use_relative_e_distances.value) {
line.set(reader, E, line.value(E) * len / total_layer_length);
} else {
last_old_E = line.value(E);
E_accumulator += line.dist_E(reader) * len / total_layer_length;
line.set(reader, E, E_accumulator);
if (boost::starts_with(line.comment()," milling"))
is_milling = true;
if (!is_milling) {
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)) {
keep_first_travel = false;
len += dist_XY;
line.set(reader, Z, z + len * layer_height_factor);
if (m_transition_layer && line.has(E)) {
// Transition layer, modulate the amount of extrusion from zero to the final value.
if (m_config.use_relative_e_distances.value) {
line.set(reader, E, line.value(E) * len / total_layer_length);
} else {
last_old_E = line.value(E);
E_accumulator += line.dist_E(reader) * len / total_layer_length;
line.set(reader, E, E_accumulator);
}
}
new_gcode += line.raw() + '\n';
} else if (keep_first_travel) {
//we can travel until the first spiral extrusion
new_gcode += line.raw() + '\n';
}
new_gcode += line.raw() + '\n';
} else if (keep_first_travel) {
//we can travel until the first spiral extrusion
new_gcode += line.raw() + '\n';
line_last_position = line;
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?). */
}
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?). */
}
}
} else if (!height_str.empty()) {
const std::string& comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
std::string comment_str = comment.substr(1);
if (boost::starts_with(comment_str, GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height))) {
//do not write it on the gcode
return;
} else if (!height_str.empty()) {
const std::string& comment = line.raw();
if (comment.length() > 2 && comment.front() == ';') {
std::string comment_str = comment.substr(1);
if (boost::starts_with(comment_str, GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height))) {
//do not write it on the gcode
return;
}
}
}
if (m_transition_layer && !m_config.use_relative_e_distances.value) {
new_gcode += "; End spiral transition layer\n";
new_gcode += "G92 E" + to_string_nozero(last_old_E, m_config.gcode_precision_e.value) + "\n";
}
new_gcode += line.raw() + '\n';
} else {
//milling, just copy
new_gcode += line.raw() + '\n';
}
if (m_transition_layer && !m_config.use_relative_e_distances.value) {
new_gcode += "; End spiral transition layer\n";
new_gcode += "G92 E"+ to_string_nozero(last_old_E, m_config.gcode_precision_e.value) + "\n";
}
new_gcode += line.raw() + '\n';
});
if (m_transition_layer && !height_str.empty()) {
//restore height/width
new_gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + height_str +"\n";
}
if (is_milling) {
//travel back to last good position.
line_last_position.set(m_reader, Axis::E, 0);
new_gcode += "; return to spiral location\n";
new_gcode += line_last_position.raw() + "\n";
}

return new_gcode;
}
Expand Down
3 changes: 3 additions & 0 deletions src/libslic3r/PerimeterGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,9 @@ void PerimeterGenerator::process()
if (unmillable.empty())
last = offset_ex(last, mill_extra_size);
else {
//FIXME only work if mill_extra_size < mill_nozzle/2 (becasue it's the extra offset from unmillable)
//FIXME overhangs if mill_extra_size is too big
//FIXME merge with process_arachne?
ExPolygons growth = diff_ex(offset_ex(last, mill_extra_size), unmillable, ApplySafetyOffset::Yes);
last.insert(last.end(), growth.begin(), growth.end());
last = union_ex(last);
Expand Down
32 changes: 21 additions & 11 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2989,16 +2989,16 @@ void TabPrinter::milling_count_changed(size_t milling_count)
is_count_changed = true;
}

/* This function should be call in any case because of correct updating/rebuilding
* of unregular pages of a Printer Settings
*/
build_unregular_pages(false);
if (is_count_changed) {
/* This function should be call in any case because of correct updating/rebuilding
* of unregular pages of a Printer Settings
*/
build_unregular_pages(false);

//no gui listing for now
//if (is_count_changed) {
// on_value_change("milling_count", milling_count);
// wxGetApp().sidebar().update_objects_list_milling_column(milling_count);
//}
//propagate change
on_value_change("milling_count", milling_count);
//wxGetApp().sidebar().update_objects_list_milling_column(milling_count);
}
}

void TabPrinter::append_option_line_kinematics(ConfigOptionsGroupShp optgroup, const std::string opt_key, const std::string override_sidetext)
Expand Down Expand Up @@ -3287,8 +3287,10 @@ void TabPrinter::reload_config()

// "extruders_count" doesn't update from the update_config(),
// so update it implicitly
if (m_active_page && m_active_page->title() == "General")
if (m_active_page && m_active_page->get_field("extruders_count"))
m_active_page->set_value("extruders_count", int(m_extruders_count));
if (m_active_page && m_active_page->get_field("milling_count"))
m_active_page->set_value("milling_count", int(m_milling_count));
}

void TabPrinter::activate_selected_page(std::function<void()> throw_if_canceled)
Expand All @@ -3297,8 +3299,10 @@ void TabPrinter::activate_selected_page(std::function<void()> throw_if_canceled)

// "extruders_count" doesn't update from the update_config(),
// so update it implicitly
if (m_active_page && m_active_page->title() == "General")
if (m_active_page && m_active_page->get_field("extruders_count"))
m_active_page->set_value("extruders_count", int(m_extruders_count));
if (m_active_page && m_active_page->get_field("milling_count"))
m_active_page->set_value("milling_count", int(m_milling_count));
}

void TabPrinter::clear_pages()
Expand Down Expand Up @@ -4732,13 +4736,19 @@ void TabPrinter::cache_extruder_cnt()
return;

m_cache_extruder_count = m_extruders_count;
m_cache_milling_count = m_milling_count;
}

bool TabPrinter::apply_extruder_cnt_from_cache()
{
if (m_presets->get_edited_preset().printer_technology() == ptSLA)
return false;

if (m_cache_milling_count > 0) {
m_presets->get_edited_preset().set_num_milling(m_cache_milling_count);
m_cache_milling_count = 0;
}

if (m_cache_extruder_count > 0) {
m_presets->get_edited_preset().set_num_extruders(m_cache_extruder_count);
m_cache_extruder_count = 0;
Expand Down

0 comments on commit 3466946

Please sign in to comment.