From 6ab1cec48c037a4f4a132a06e83f2a12fcacd9ff Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 2 Aug 2019 16:49:22 +0200 Subject: [PATCH] Empty layers detection added to GCode.cpp Added detection of empty layers so the wipe tower doesn't trip on them (it is not printable anyway). This should improve wipe tower reliability with supports, objects standing on edges, etc. I also turned an assert into exception throw to prevent hard crashes and nonsense output. --- src/libslic3r/GCode.cpp | 18 +++++++++++++++++- src/libslic3r/GCode/ToolOrdering.cpp | 10 ++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 011bf3fc4..6ae703a20 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1,4 +1,5 @@ #include "libslic3r.h" +#include "I18N.hpp" #include "GCode.hpp" #include "ExtrusionEntity.hpp" #include "EdgeGrid.hpp" @@ -36,6 +37,11 @@ namespace Slic3r { +//! macro used to mark string used at localization, +//! return same string +#define L(s) (s) +#define _(s) Slic3r::I18N::translate(s) + // Only add a newline in case the current G-code does not end with a newline. static inline void check_add_eol(std::string &gcode) { @@ -405,7 +411,8 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, assert(m_layer_idx >= 0 && size_t(m_layer_idx) <= m_tool_changes.size()); if (! m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) { if (m_layer_idx < (int)m_tool_changes.size()) { - assert(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()); + if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size())) + throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer."); gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id); } m_brim_done = true; @@ -436,6 +443,14 @@ std::vector GCode::collect_layers_to_print(const PrintObjec size_t idx_object_layer = 0; size_t idx_support_layer = 0; while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { + // Let's make sure that the last layer is not empty, so we don't build on top of it. + if (! layers_to_print.empty() + && (! layers_to_print.back().object_layer || ! layers_to_print.back().object_layer->has_extrusions()) + && (! layers_to_print.back().support_layer || ! layers_to_print.back().support_layer->has_extrusions())) + throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" + + _(L("Object name: ")) + object.model_object()->name + "\n" + _(L("Print z: ")) + + std::to_string(layers_to_print.back().print_z())); + LayerToPrint layer_to_print; layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer ++] : nullptr; layer_to_print.support_layer = (idx_support_layer < object.support_layers().size()) ? object.support_layers()[idx_support_layer ++] : nullptr; @@ -448,6 +463,7 @@ std::vector GCode::collect_layers_to_print(const PrintObjec -- idx_object_layer; } } + layers_to_print.emplace_back(layer_to_print); } diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index f10b45723..18437c8e1 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -78,8 +78,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool zs.emplace_back(layer->print_z); for (auto layer : object->support_layers()) zs.emplace_back(layer->print_z); - if (! object->layers().empty()) - object_bottom_z = object->layers().front()->print_z - object->layers().front()->height; + + // Find first object layer that is not empty and save its print_z + for (const Layer* layer : object->layers()) + if (layer->has_extrusions()) { + object_bottom_z = layer->print_z - layer->height; + break; + } } this->initialize_layers(zs); } @@ -324,6 +329,7 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ m_layer_tools[j].has_wipe_tower = true; } else { LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); + //LayerTools <_prev = m_layer_tools[j]; LayerTools <_next = m_layer_tools[j + 1]; assert(! m_layer_tools[j - 1].extruders.empty() && ! lt_next.extruders.empty()); // FIXME: Following assert tripped when running combine_infill.t. I decided to comment it out for now.