From ad65cdb909b29210117f690a119ef76b70373da4 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Mon, 22 Jul 2024 20:09:58 +0800 Subject: [PATCH] ENH: add filament saved by multi extruder 1.Add filament flush,filament change count reduced by multi extruder NTOE: cases when printing by object haven't been handled jira:NONE Signed-off-by: xun.zhang Change-Id: Iaaea5f8ffae2345df5a6f1dc605342d835974d48 --- src/libslic3r/GCode/ToolOrdering.cpp | 51 ++++++++++++++++++++++++++++ src/libslic3r/GCode/ToolOrdering.hpp | 17 ++++++++-- src/libslic3r/Print.cpp | 12 +++++++ src/libslic3r/Print.hpp | 15 ++++++++ src/slic3r/GUI/GCodeViewer.cpp | 7 ++-- 5 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index a025f4292..78d0136cd 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -447,6 +447,37 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object return std::max(max_layer_height, max_object_layer_height); } +//calculate the flush weight (first value) and filament change count(second value) +static std::pair calc_filament_change_info_by_toolorder(const PrintConfig* config,const std::vector&filament_map,const std::vector&flush_matrix,const std::vector>&layer_sequences) +{ + std::map flush_volume_per_filament; + + std::vectorlast_filament_per_extruder(2, -1); + + int total_filament_change_count = 0; + int total_filament_flush_weight = 0; + for (const auto& ls : layer_sequences) { + for (const auto& item : ls) { + int extruder_id = filament_map[item]; + int last_filament = last_filament_per_extruder[extruder_id]; + if (last_filament != -1 && last_filament != item) { + int flush_volume = flush_matrix[extruder_id][last_filament][item]; + flush_volume_per_filament[item] += flush_volume; + total_filament_change_count += 1; + } + last_filament_per_extruder[extruder_id] = item; + } + } + + for (auto& fv : flush_volume_per_filament) { + int weight = config->filament_density.get_at(fv.first) * 0.001 * fv.second; + total_filament_flush_weight += weight; + } + + return { total_filament_flush_weight,total_filament_change_count }; +} + + // For the use case when each object is printed separately // (print->config().print_sequence == PrintSequence::ByObject is true). ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material) @@ -1315,6 +1346,26 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first &filament_sequences ); + auto curr_flush_info = calc_filament_change_info_by_toolorder(print_config, filament_maps, nozzle_flush_mtx, filament_sequences); + m_curr_flush_info = curr_flush_info; + + if (nozzle_nums > 1) { + std::vector>filament_sequences_one_extruder; + auto maps_without_group = filament_maps; + for (auto& item : maps_without_group) + item = 0; + reorder_filaments_for_minimum_flush_volume( + filament_lists, + maps_without_group, + layer_filaments, + nozzle_flush_mtx, + get_custom_seq, + &filament_sequences_one_extruder + ); + auto one_extruder_flush_info = calc_filament_change_info_by_toolorder(print_config, maps_without_group, nozzle_flush_mtx, filament_sequences_one_extruder); + m_one_extruder_flush_info = one_extruder_flush_info; + } + for (size_t i = 0; i < filament_sequences.size(); ++i) m_layer_tools[i].extruders = std::move(filament_sequences[i]); } diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 1de23f63b..599938c42 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -156,6 +156,10 @@ private: class ToolOrdering { public: + enum FlushCalcMode { + Normal=0, + OneExtruder + }; ToolOrdering() = default; // For the use case when each object is printed separately @@ -166,8 +170,10 @@ public: // (print->config().print_sequence == PrintSequence::ByObject is false). ToolOrdering(const Print& print, unsigned int first_extruder, bool prime_multi_material = false); - void clear() { - m_layer_tools.clear(); m_tool_order_cache.clear(); + void clear() { + m_layer_tools.clear(); + m_curr_flush_info = { 0,0 }; + m_one_extruder_flush_info = { 0,0 }; } // Only valid for non-sequential print: @@ -199,6 +205,9 @@ public: static std::vector get_recommended_filament_maps(const std::vector>& layer_filaments, const PrintConfig *print_config); + // first val: flush weight second val: change count + std::pair get_flush_info(int mode) const { return mode == FlushCalcMode::OneExtruder ? m_one_extruder_flush_info : m_curr_flush_info; } + private: void initialize_layers(std::vector &zs); void collect_extruders(const PrintObject &object, const std::vector> &per_layer_extruder_switches); @@ -221,10 +230,12 @@ private: unsigned int m_last_printing_extruder = (unsigned int)-1; // All extruders, which extrude some material over m_layer_tools. std::vector m_all_printing_extruders; - std::unordered_map> m_tool_order_cache; const PrintConfig* m_print_config_ptr = nullptr; const PrintObject* m_print_object_ptr = nullptr; Print* m_print; + + std::pair m_curr_flush_info{ 0,0 }; + std::pair m_one_extruder_flush_info{ 0,0 }; }; } // namespace SLic3r diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a3182c04c..9a44dd3b9 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1814,6 +1814,12 @@ void Print::process(std::unordered_map* slice_time, bool m_tool_ordering = ToolOrdering(*this, -1, false); if (m_tool_ordering.empty() || m_tool_ordering.last_extruder() == unsigned(-1)) throw Slic3r::SlicingError("The print is empty. The model is not printable with current print settings."); + + std::pair curr_info = m_tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal); + std::pair single_extruder_info = m_tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::OneExtruder); + + this->m_statistics_by_extruder_count.filament_flush_weight = { curr_info.first,single_extruder_info.first }; + this->m_statistics_by_extruder_count.filament_change_count = { curr_info.second,single_extruder_info.second }; } this->set_done(psWipeTower); } @@ -2407,6 +2413,12 @@ void Print::_make_wipe_tower() // BBS: priming logic is removed, so don't consider it in tool ordering m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, false); + std::pair curr_info = m_wipe_tower_data.tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal); + std::pair single_extruder_info = m_wipe_tower_data.tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::OneExtruder); + + this->m_statistics_by_extruder_count.filament_flush_weight = { curr_info.first,single_extruder_info.first }; + this->m_statistics_by_extruder_count.filament_change_count = { curr_info.second,single_extruder_info.second }; + if (!m_wipe_tower_data.tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index bf8c90988..b5c6e92dc 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -695,6 +695,17 @@ class ConstPrintRegionPtrsAdaptor : public ConstVectorOfPtrsAdaptor }; */ +struct StatisticsByExtruderCount +{ + // multi extruder always comes first + std::vector filament_flush_weight{ 0,0 }; + std::vector filament_change_count{ 0,0 }; + void clear() { + filament_flush_weight.clear(); + filament_change_count.clear(); + } +}; + enum FilamentTempType { HighTemp=0, LowTemp, @@ -800,6 +811,9 @@ public: const PrintStatistics& print_statistics() const { return m_print_statistics; } PrintStatistics& print_statistics() { return m_print_statistics; } + const StatisticsByExtruderCount statistics_by_extruder() const { return m_statistics_by_extruder_count; } + StatisticsByExtruderCount& statistics_by_extruder() { return m_statistics_by_extruder_count; } + // Wipe tower support. bool has_wipe_tower() const; const WipeTowerData& wipe_tower_data(size_t filaments_cnt = 0) const; @@ -915,6 +929,7 @@ private: // Estimated print time, filament consumed. PrintStatistics m_print_statistics; bool m_support_used {false}; + StatisticsByExtruderCount m_statistics_by_extruder_count; //BBS: plate's origin Vec3d m_origin; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 47d578975..1ccee3360 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4633,6 +4633,7 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding) ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(window_padding * 3, 0)); ImGui::BeginChild("#AMS", ImVec2(0, AMS_container_height), false, ImGuiWindowFlags_AlwaysUseWindowPadding); { + auto stats_by_extruder = wxGetApp().plater()->get_partplate_list().get_current_fff_print().statistics_by_extruder(); // BBS save time; imgui.text(_u8L("Since you set 1 AMS")); ImGui::SameLine(); @@ -4640,8 +4641,10 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding) link_text(_u8L("(change)")); ImGui::SameLine(); imgui.text(_u8L(",this arrangement would be optimal.")); - imgui.text(_u8L("It will save 738g filament and 23 minutes")); - + int delta_filament_weight = stats_by_extruder.filament_flush_weight[1] - stats_by_extruder.filament_flush_weight[0]; + int delta_filament_change = stats_by_extruder.filament_change_count[1] - stats_by_extruder.filament_change_count[0]; + imgui.text(from_u8((boost::format(_u8L("Info by single extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.filament_flush_weight[1] % stats_by_extruder.filament_change_count[1]).str())); + imgui.text(from_u8((boost::format(_u8L("Info by multi extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.filament_flush_weight[0] % stats_by_extruder.filament_change_count[0]).str())); float available_width = ImGui::GetContentRegionAvail().x; float available_height = ImGui::GetContentRegionAvail().y; float half_width = available_width * 0.5f;