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 <xun.zhang@bambulab.com>
Change-Id: Iaaea5f8ffae2345df5a6f1dc605342d835974d48
This commit is contained in:
xun.zhang 2024-07-22 20:09:58 +08:00 committed by lane.wei
parent 3a55a3a1ee
commit ad65cdb909
5 changed files with 97 additions and 5 deletions

View File

@ -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<int,int> calc_filament_change_info_by_toolorder(const PrintConfig* config,const std::vector<int>&filament_map,const std::vector<FlushMatrix>&flush_matrix,const std::vector<std::vector<unsigned int>>&layer_sequences)
{
std::map<int, int> flush_volume_per_filament;
std::vector<unsigned int>last_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<std::vector<unsigned int>>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]);
}

View File

@ -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<int> get_recommended_filament_maps(const std::vector<std::vector<unsigned int>>& layer_filaments, const PrintConfig *print_config);
// first val: flush weight second val: change count
std::pair<int, int> 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<coordf_t> &zs);
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &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<unsigned int> m_all_printing_extruders;
std::unordered_map<uint32_t, std::vector<uint8_t>> m_tool_order_cache;
const PrintConfig* m_print_config_ptr = nullptr;
const PrintObject* m_print_object_ptr = nullptr;
Print* m_print;
std::pair<int, int> m_curr_flush_info{ 0,0 };
std::pair<int, int> m_one_extruder_flush_info{ 0,0 };
};
} // namespace SLic3r

View File

@ -1814,6 +1814,12 @@ void Print::process(std::unordered_map<std::string, long long>* 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<int, int> curr_info = m_tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal);
std::pair<int, int> 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<int, int> curr_info = m_wipe_tower_data.tool_ordering.get_flush_info(ToolOrdering::FlushCalcMode::Normal);
std::pair<int, int> 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;

View File

@ -695,6 +695,17 @@ class ConstPrintRegionPtrsAdaptor : public ConstVectorOfPtrsAdaptor<PrintRegion>
};
*/
struct StatisticsByExtruderCount
{
// multi extruder always comes first
std::vector<int> filament_flush_weight{ 0,0 };
std::vector<int> 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;

View File

@ -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;