From 2178180a19e79c58fa42fe15b68f0fb9dd233033 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 30 May 2017 10:51:38 +0200 Subject: [PATCH] Wipe tower: Wipe less than usual amount of material if the wipe is followed by the final sparse zig-zag tower section. --- xs/src/libslic3r/GCode/ToolOrdering.cpp | 2 +- xs/src/libslic3r/GCode/WipeTower.hpp | 2 +- xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 48 ++++++++++++++++++--- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 2 +- xs/src/libslic3r/Print.cpp | 4 +- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index 789b499fc..c233d81f6 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -244,7 +244,7 @@ void ToolOrdering::fill_wipe_tower_partitions() //FIXME this is a hack to get the ball rolling. for (LayerTools < : m_layer_tools) - lt.has_wipe_tower = lt.has_object; + lt.has_wipe_tower = lt.has_object && lt.wipe_tower_partitions > 0; } } // namespace Slic3r diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 95c6f6f63..ceb6921f1 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -92,7 +92,7 @@ public: // Returns gcode for toolchange and the end position. // if new_tool == -1, just unload the current filament over the wipe tower. - virtual ToolChangeResult tool_change(int new_tool, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; + virtual ToolChangeResult tool_change(int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; // Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag. // Call this method only if layer_finished() is false. diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 51db1a552..199a6210c 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -340,7 +340,7 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam return INVALID; } -WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, Purpose purpose) +WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, bool last_in_layer, Purpose purpose) { // Either it is the last tool unload, // or there must be a nonzero wipe tower partitions available. @@ -351,10 +351,47 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, Purpose purp return toolchange_Brim(purpose); } + float wipe_area = m_wipe_area; + if (++ m_idx_tool_change_in_layer < (unsigned int)m_max_color_changes && last_in_layer) { + // This tool_change() call will be followed by a finish_layer() call. + // Try to shrink the wipe_area to save material, as less than usual wipe is required + // if this step is foolowed by finish_layer() extrusions wiping the same extruder. + for (size_t iter = 0; iter < 3; ++ iter) { + // Simulate the finish_layer() extrusions, summ the length of the extrusion. + float e_length = 0.f; + { + unsigned int old_idx_tool_change = m_idx_tool_change_in_layer; + float old_wipe_start_y = m_current_wipe_start_y; + m_current_wipe_start_y += wipe_area; + ToolChangeResult tcr = this->finish_layer(PURPOSE_EXTRUDE); + for (size_t i = 1; i < tcr.extrusions.size(); ++ i) { + const Extrusion &e = tcr.extrusions[i]; + if (e.width > 0) { + xy v = e.pos - (&e - 1)->pos; + e_length += sqrt(v.x*v.x+v.y*v.y); + } + } + m_idx_tool_change_in_layer = old_idx_tool_change; + m_current_wipe_start_y = old_wipe_start_y; + } + // Shrink wipe_area by the amount of extrusion extruded by the finish_layer(). + // Y stepping of the wipe extrusions. + float dy = m_perimeter_width * 0.8f; + // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer(). + float num_lines_extruded = floor(e_length / m_wipe_tower_width); + // Minimum wipe area is 5mm wide. + wipe_area -= num_lines_extruded * dy; + if (wipe_area < 5.) { + wipe_area = 5.; + break; + } + } + } + box_coordinates cleaning_box( m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y + 0.5f * m_perimeter_width), m_wipe_tower_width, - m_wipe_area - m_perimeter_width); + wipe_area - m_perimeter_width); PrusaMultiMaterial::Writer writer; writer.set_extrusion_flow(m_extrusion_flow) @@ -430,8 +467,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, Purpose purp "\n\n"); ++ m_num_tool_changes; - ++ m_idx_tool_change_in_layer; - m_current_wipe_start_y += m_wipe_area; + m_current_wipe_start_y += wipe_area; } ToolChangeResult result; @@ -728,8 +764,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) // Slow down on the 1st layer. float speed_factor = m_is_first_layer ? 0.5f : 1.f; - box_coordinates fill_box(m_wipe_tower_pos + xy(0.f, float(m_idx_tool_change_in_layer) * m_wipe_area), - m_wipe_tower_width, float(m_max_color_changes - m_idx_tool_change_in_layer) * m_wipe_area); + box_coordinates fill_box(m_wipe_tower_pos + xy(0.f, m_current_wipe_start_y), + m_wipe_tower_width, float(m_max_color_changes) * m_wipe_area - m_current_wipe_start_y); fill_box.expand(0.f, - 0.5f * m_perimeter_width); { float firstLayerOffset = 0.f; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 2889c30e3..329ee6f57 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -117,7 +117,7 @@ public: // Returns gcode for a toolchange and a final print head position. // On the first layer, extrude a brim around the future wipe tower first. - virtual ToolChangeResult tool_change(int new_tool, Purpose purpose); + virtual ToolChangeResult tool_change(int new_tool, bool last_in_layer, Purpose purpose); // Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag. // Call this method only if layer_finished() is false. diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 876dd39ad..ab5babcaa 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1062,7 +1062,7 @@ void Print::_make_wipe_tower() std::vector tool_changes; for (unsigned int extruder_id : layer_tools.extruders) if ((first_layer && extruder_id == initial_extruder_id) || extruder_id != current_extruder_id) { - tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, WipeTower::PURPOSE_EXTRUDE)); + tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, extruder_id == layer_tools.extruders.back(), WipeTower::PURPOSE_EXTRUDE)); current_extruder_id = extruder_id; } if (! wipe_tower.layer_finished()) { @@ -1105,7 +1105,7 @@ void Print::_make_wipe_tower() wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true); } m_wipe_tower_final_purge = Slic3r::make_unique( - wipe_tower.tool_change(-1, WipeTower::PURPOSE_EXTRUDE)); + wipe_tower.tool_change(-1, false, WipeTower::PURPOSE_EXTRUDE)); } std::string Print::output_filename()