From 61e6f23ed2d3366cc7370ba75ddd0d1c1404f6f5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 11 Dec 2017 17:19:55 +0100 Subject: [PATCH] Fix of "Multimaterial printer switches filament at the wrong time during a print" https://github.com/prusa3d/Slic3r/issues/607 There was a single layer between the raft top and the object first layer missing on the wipe tower, and after this missing layer all the tool changes were shifted by one layer, meaning two color print had the colors switched. --- xs/src/libslic3r/GCode/ToolOrdering.cpp | 28 +++++++++++++++---- xs/src/libslic3r/GCode/ToolOrdering.hpp | 2 ++ xs/src/libslic3r/Layer.hpp | 4 ++- xs/src/libslic3r/Print.cpp | 37 +++++++++++++++++++++++++ xs/src/libslic3r/SupportMaterial.cpp | 12 ++------ xs/xsp/Layer.xsp | 26 ----------------- xs/xsp/Print.xsp | 1 - 7 files changed, 67 insertions(+), 43 deletions(-) diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index 0ffdbcc434..a8954eca51 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -1,7 +1,16 @@ #include "Print.hpp" #include "ToolOrdering.hpp" -#include +// #define SLIC3R_DEBUG + +// Make assert active if SLIC3R_DEBUG +#ifdef SLIC3R_DEBUG + #define DEBUG + #define _DEBUG + #undef NDEBUG +#endif + +#include #include namespace Slic3r { @@ -257,11 +266,18 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z)); // Find the 1st layer above lt_new. for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z; ++ j); - LayerTools <_extra = (m_layer_tools[j].print_z == lt_new.print_z) ? - m_layer_tools[j] : - *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); - lt_extra.has_wipe_tower = true; - lt_extra.wipe_tower_partitions = lt_object.wipe_tower_partitions; + if (m_layer_tools[j].print_z == lt_new.print_z) { + 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 - 1]; + LayerTools <_next = m_layer_tools[j + 1]; + assert(! lt_prev.extruders.empty() && ! lt_next.extruders.empty()); + assert(lt_prev.extruders.back() == lt_next.extruders.front()); + lt_extra.has_wipe_tower = true; + lt_extra.extruders.push_back(lt_next.extruders.front()); + lt_extra.wipe_tower_partitions = lt_next.wipe_tower_partitions; + } } } break; diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/xs/src/libslic3r/GCode/ToolOrdering.hpp index abf1aa6b20..c92806b19b 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.hpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.hpp @@ -69,6 +69,8 @@ public: const LayerTools& front() const { return m_layer_tools.front(); } const LayerTools& back() const { return m_layer_tools.back(); } + std::vector::const_iterator begin() const { return m_layer_tools.begin(); } + std::vector::const_iterator end() const { return m_layer_tools.end(); } bool empty() const { return m_layer_tools.empty(); } const std::vector& layer_tools() const { return m_layer_tools; } bool has_wipe_tower() const { return ! m_layer_tools.empty() && m_first_printing_extruder != (unsigned int)-1 && m_layer_tools.front().wipe_tower_partitions > 0; } diff --git a/xs/src/libslic3r/Layer.hpp b/xs/src/libslic3r/Layer.hpp index f8fdcdd4d2..f3b4604430 100644 --- a/xs/src/libslic3r/Layer.hpp +++ b/xs/src/libslic3r/Layer.hpp @@ -161,7 +161,9 @@ public: // Is there any valid extrusion assigned to this LayerRegion? virtual bool has_extrusions() const { return ! support_fills.empty(); } -protected: +//protected: + // The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower + // between the raft and the object first layer. SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) : Layer(id, object, height, print_z, slice_z) {} virtual ~SupportLayer() {} diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 190fbfe6ed..7739983944 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -978,6 +978,43 @@ void Print::_make_wipe_tower() // Don't generate any wipe tower. return; + // Check whether there are any layers in m_tool_ordering, which are marked with has_wipe_tower, + // they print neither object, nor support. These layers are above the raft and below the object, and they + // shall be added to the support layers to be printed. + // see https://github.com/prusa3d/Slic3r/issues/607 + { + size_t idx_begin = size_t(-1); + size_t idx_end = m_tool_ordering.layer_tools().size(); + // Find the first wipe tower layer, which does not have a counterpart in an object or a support layer. + for (size_t i = 0; i < idx_end; ++ i) { + const ToolOrdering::LayerTools < = m_tool_ordering.layer_tools()[i]; + if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) { + idx_begin = i; + break; + } + } + if (idx_begin != size_t(-1)) { + // Find the position in this->objects.first()->support_layers to insert these new support layers. + double wipe_tower_new_layer_print_z_first = m_tool_ordering.layer_tools()[idx_begin].print_z; + SupportLayerPtrs::iterator it_layer = this->objects.front()->support_layers.begin(); + for (; (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer) ; + // Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer. + for (size_t i = idx_begin; i < idx_end; ++ i) { + ToolOrdering::LayerTools < = const_cast(m_tool_ordering.layer_tools()[i]); + if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support)) + break; + lt.has_support = true; + // Insert the new support layer. + //FIXME the support layer ID is duplicated, but Vojtech hopes it is not being used anywhere anyway. + double height = lt.print_z - m_tool_ordering.layer_tools()[i-1].print_z; + auto *new_layer = new SupportLayer((*it_layer)->id(), this->objects.front(), + height, lt.print_z, lt.print_z - 0.5 * height); + it_layer = this->objects.front()->support_layers.insert(it_layer, new_layer); + ++ it_layer; + } + } + } + // Initialize the wipe tower. WipeTowerPrusaMM wipe_tower( float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 07943fb15a..b8df67ba6b 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -373,15 +373,9 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) height_min = std::min(height_min, layer.height); } if (! empty) { - object.add_support_layer(layer_id, height_min, zavg); - if (layer_id > 0) { - // Inter-link the support layers into a linked list. - SupportLayer *sl1 = object.support_layers[object.support_layer_count() - 2]; - SupportLayer *sl2 = object.support_layers.back(); - sl1->upper_layer = sl2; - sl2->lower_layer = sl1; - } - ++layer_id; + // Here the upper_layer and lower_layer pointers are left to null at the support layers, + // as they are never used. These pointers are candidates for removal. + object.add_support_layer(layer_id ++, height_min, zavg); } i = j; } diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index 71fc540dc2..4f09fb5214 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -50,10 +50,6 @@ int id(); void set_id(int id); Ref object(); - Ref upper_layer() - %code%{ RETVAL = THIS->upper_layer; %}; - Ref lower_layer() - %code%{ RETVAL = THIS->lower_layer; %}; bool slicing_errors() %code%{ RETVAL = THIS->slicing_errors; %}; coordf_t slice_z() @@ -63,15 +59,6 @@ coordf_t height() %code%{ RETVAL = THIS->height; %}; - void set_upper_layer(Layer *layer) - %code%{ THIS->upper_layer = layer; %}; - void set_lower_layer(Layer *layer) - %code%{ THIS->lower_layer = layer; %}; - bool has_upper_layer() - %code%{ RETVAL = (THIS->upper_layer != NULL); %}; - bool has_lower_layer() - %code%{ RETVAL = (THIS->lower_layer != NULL); %}; - size_t region_count(); Ref get_region(int idx); Ref add_region(PrintRegion* print_region); @@ -112,10 +99,6 @@ int id(); void set_id(int id); Ref object(); - Ref upper_layer() - %code%{ RETVAL = (SupportLayer*)THIS->upper_layer; %}; - Ref lower_layer() - %code%{ RETVAL = (SupportLayer*)THIS->lower_layer; %}; bool slicing_errors() %code%{ RETVAL = THIS->slicing_errors; %}; coordf_t slice_z() @@ -125,15 +108,6 @@ coordf_t height() %code%{ RETVAL = THIS->height; %}; - void set_upper_layer(SupportLayer *layer) - %code%{ THIS->upper_layer = layer; %}; - void set_lower_layer(SupportLayer *layer) - %code%{ THIS->lower_layer = layer; %}; - bool has_upper_layer() - %code%{ RETVAL = (THIS->upper_layer != NULL); %}; - bool has_lower_layer() - %code%{ RETVAL = (THIS->lower_layer != NULL); %}; - size_t region_count(); Ref get_region(int idx); Ref add_region(PrintRegion* print_region); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 1148fd4aa6..2e418253b0 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -91,7 +91,6 @@ _constant() size_t support_layer_count(); void clear_support_layers(); Ref get_support_layer(int idx); - Ref add_support_layer(int id, coordf_t height, coordf_t print_z); bool step_done(PrintObjectStep step) %code%{ RETVAL = THIS->state.is_done(step); %};