From 2dbc5c939666e294c805ee4bf33ec09976688be3 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Thu, 25 Jul 2024 11:37:15 +0800 Subject: [PATCH] ENH: add manual grouping mode stats 1.In auto mode,display the statistics of auto mode and single extruder 2.In manual mode,display the statistics of manual mode and auto mode 3.Support by object mode jira:NONE Signed-off-by: xun.zhang Change-Id: If54c4db79f33d5278c0f18d01ab0518e8660f9c7 --- src/libslic3r/GCode.cpp | 12 +++++ src/libslic3r/GCode/ToolOrdering.cpp | 80 +++++++++++++++++++++------- src/libslic3r/GCode/ToolOrdering.hpp | 52 ++++++++++++++---- src/libslic3r/Print.cpp | 19 ++----- src/libslic3r/Print.hpp | 14 ++--- src/slic3r/GUI/GCodeViewer.cpp | 16 ++++-- 6 files changed, 142 insertions(+), 51 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 51032b052..0971efb57 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1748,6 +1748,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato unsigned int initial_non_support_extruder_id; unsigned int final_extruder_id = (unsigned int)-1; bool has_wipe_tower = false; + print.m_statistics_by_extruder_count.clear(); + std::vector print_object_instances_ordering; std::vector::const_iterator print_object_instance_sequential_active; if (print.config().print_sequence == PrintSequence::ByObject) { @@ -1758,6 +1760,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato print_object_instance_sequential_active = print_object_instances_ordering.begin(); for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) { tool_ordering = ToolOrdering(*(*print_object_instance_sequential_active)->print_object, initial_extruder_id); + { //save the flush statitics stored in tool ordering by object + print.m_statistics_by_extruder_count.stats_by_single_extruder += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::SingleExt); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_auto += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtAuto); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_manual += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtManual); + } if ((initial_extruder_id = tool_ordering.first_extruder()) != static_cast(-1)) { //BBS: try to find the non-support filament extruder if is multi color and initial_extruder is support filament initial_non_support_extruder_id = initial_extruder_id; @@ -1804,6 +1811,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato // Find tool ordering for all the objects at once, and the initial extruder ID. // If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it. tool_ordering = print.tool_ordering(); + { //save the flush statitics stored in tool ordering + print.m_statistics_by_extruder_count.stats_by_single_extruder = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::SingleExt); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_auto = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtAuto); + print.m_statistics_by_extruder_count.stats_by_multi_extruder_manual = tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::MultiExtManual); + } tool_ordering.assign_custom_gcodes(print); if (tool_ordering.all_extruders().empty()) // No object to print was found, cancel the G-code export. diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 9835bcffe..fb708ea98 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -456,10 +456,10 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object } //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) +static FilamentChangeStats calc_filament_change_info_by_toolorder(const PrintConfig* config,const std::vector&filament_map,const std::vector&flush_matrix,const std::vector>&layer_sequences) { + FilamentChangeStats ret; std::map flush_volume_per_filament; - std::vectorlast_filament_per_extruder(2, -1); int total_filament_change_count = 0; @@ -482,7 +482,10 @@ static std::pair calc_filament_change_info_by_toolorder(const PrintConf total_filament_flush_weight += weight; } - return { total_filament_flush_weight,total_filament_change_count }; + ret.filament_change_count = total_filament_change_count; + ret.filament_flush_weight = total_filament_flush_weight; + + return ret; } @@ -1258,6 +1261,22 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vectorfilament_maps(number_of_extruders, 0); + FilamentMapMode map_mode = FilamentMapMode::fmmAuto; if (nozzle_nums > 1) { filament_maps = m_print->get_filament_maps(); - if (m_print->get_filament_map_mode() == FilamentMapMode::fmmAuto + map_mode = m_print->get_filament_map_mode(); + if (map_mode == FilamentMapMode::fmmAuto && (print_config->print_sequence != PrintSequence::ByObject || m_print->objects().size() == 1)) { const PrintConfig* print_config = m_print_config_ptr; if (!print_config && m_print_object_ptr) { @@ -1355,23 +1376,46 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first ); 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) + m_stats_by_single_extruder = curr_flush_info; + else if (map_mode == fmmAuto) + m_stats_by_multi_extruder_auto = curr_flush_info; + else if (map_mode == fmmManual) + m_stats_by_multi_extruder_manual = curr_flush_info; + // in multi extruder mode 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 + // always calculate the info by one extruder + { + 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; + m_stats_by_single_extruder = calc_filament_change_info_by_toolorder(print_config, maps_without_group, nozzle_flush_mtx, filament_sequences_one_extruder); + } + // if in manual mode,also calculate the info by auto mode + if (map_mode == fmmManual) + { + std::vector>filament_sequences_one_extruder; + std::vectorfilament_maps_auto = get_recommended_filament_maps(layer_filaments, print_config); + reorder_filaments_for_minimum_flush_volume( + filament_lists, + filament_maps_auto, + layer_filaments, + nozzle_flush_mtx, + get_custom_seq, + &filament_sequences_one_extruder + ); + m_stats_by_multi_extruder_auto = calc_filament_change_info_by_toolorder(print_config, filament_maps_auto, nozzle_flush_mtx, filament_sequences_one_extruder); + } } for (size_t i = 0; i < filament_sequences.size(); ++i) diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 599938c42..3636378c9 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -101,6 +101,37 @@ private: const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to }; + +struct FilamentChangeStats +{ + int filament_flush_weight{0}; + int filament_change_count{0}; + int extruder_change_count{0}; + + void clear(){ + filament_flush_weight = 0; + filament_change_count = 0; + extruder_change_count = 0; + } + + FilamentChangeStats& operator+=(const FilamentChangeStats& other) { + this->filament_flush_weight += other.filament_flush_weight; + this->filament_change_count += other.filament_change_count; + this->extruder_change_count += other.extruder_change_count; + return *this; + } + + FilamentChangeStats operator+(const FilamentChangeStats& other){ + FilamentChangeStats ret; + ret.filament_flush_weight = this->filament_flush_weight + other.filament_flush_weight; + ret.filament_change_count = this->filament_change_count + other.filament_change_count; + ret.extruder_change_count = this->extruder_change_count + other.extruder_change_count; + return ret; + } + +}; + + class LayerTools { public: @@ -156,9 +187,10 @@ private: class ToolOrdering { public: - enum FlushCalcMode { - Normal=0, - OneExtruder + enum FilamentChangeMode { + SingleExt, + MultiExtAuto, + MultiExtManual }; ToolOrdering() = default; @@ -172,8 +204,9 @@ public: void clear() { m_layer_tools.clear(); - m_curr_flush_info = { 0,0 }; - m_one_extruder_flush_info = { 0,0 }; + m_stats_by_single_extruder.clear(); + m_stats_by_multi_extruder_auto.clear(); + m_stats_by_multi_extruder_manual.clear(); } // Only valid for non-sequential print: @@ -205,8 +238,8 @@ 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; } + // should be called after doing reorder + FilamentChangeStats get_filament_change_stats(FilamentChangeMode mode); private: void initialize_layers(std::vector &zs); @@ -234,8 +267,9 @@ private: 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 }; + FilamentChangeStats m_stats_by_single_extruder; + FilamentChangeStats m_stats_by_multi_extruder_manual; + FilamentChangeStats m_stats_by_multi_extruder_auto; }; } // namespace SLic3r diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 9a44dd3b9..f81ef5c44 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -64,6 +64,7 @@ void Print::clear() m_objects.clear(); m_print_regions.clear(); m_model.clear_objects(); + m_statistics_by_extruder_count.clear(); } // Called by Print::apply(). @@ -1809,17 +1810,13 @@ void Print::process(std::unordered_map* slice_time, bool m_tool_ordering.clear(); if (this->has_wipe_tower()) { this->_make_wipe_tower(); - } else if (this->config().print_sequence != PrintSequence::ByObject) { - // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches. - m_tool_ordering = ToolOrdering(*this, -1, false); + } + else if (this->config().print_sequence != PrintSequence::ByObject) { + // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches. + 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); } @@ -2413,12 +2410,6 @@ 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 b5c6e92dc..93358285b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -697,12 +697,14 @@ 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 }; + // flush weight comes first,then comes filament change time + FilamentChangeStats stats_by_single_extruder; + FilamentChangeStats stats_by_multi_extruder_auto; + FilamentChangeStats stats_by_multi_extruder_manual; void clear() { - filament_flush_weight.clear(); - filament_change_count.clear(); + stats_by_single_extruder.clear(); + stats_by_multi_extruder_auto.clear(); + stats_by_multi_extruder_manual.clear(); } }; @@ -929,7 +931,7 @@ private: // Estimated print time, filament consumed. PrintStatistics m_print_statistics; bool m_support_used {false}; - StatisticsByExtruderCount m_statistics_by_extruder_count; + 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 1ccee3360..6768f708f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4641,10 +4641,18 @@ void GCodeViewer::render_legend_color_arr_recommen(float window_padding) link_text(_u8L("(change)")); ImGui::SameLine(); imgui.text(_u8L(",this arrangement would be optimal.")); - 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())); + auto config = wxGetApp().plater()->get_partplate_list().get_current_fff_print().config(); + auto filament_map_mode = config.filament_map_mode.value; + + if (filament_map_mode == fmmAuto) { + imgui.text(from_u8((boost::format(_u8L("Info by multi extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_auto.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_auto.filament_change_count).str())); + imgui.text(from_u8((boost::format(_u8L("Info by single extruder : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_single_extruder.filament_flush_weight % stats_by_extruder.stats_by_single_extruder.filament_change_count).str())); + } + else if (filament_map_mode == fmmManual) { + imgui.text(from_u8((boost::format(_u8L("Info by manual mode : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_manual.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_manual.filament_change_count).str())); + imgui.text(from_u8((boost::format(_u8L("Info by auto mode : %1%g filament and %2% filament changes")) % stats_by_extruder.stats_by_multi_extruder_auto.filament_flush_weight % stats_by_extruder.stats_by_multi_extruder_auto.filament_change_count).str())); + } + float available_width = ImGui::GetContentRegionAvail().x; float available_height = ImGui::GetContentRegionAvail().y; float half_width = available_width * 0.5f;