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.
This commit is contained in:
Lukas Matena 2019-08-02 16:49:22 +02:00
parent 3b24565411
commit 6ab1cec48c
2 changed files with 25 additions and 3 deletions

View File

@ -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::LayerToPrint> 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::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
-- idx_object_layer;
}
}
layers_to_print.emplace_back(layer_to_print);
}

View File

@ -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 &lt_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new);
//LayerTools &lt_prev = m_layer_tools[j];
LayerTools &lt_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.