From cddf8cae27f4320f830b463e92703d3a6cf344e7 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Fri, 12 Jul 2024 18:04:01 +0800 Subject: [PATCH] ENH: add filament group strategy 1.When capacity is greater than the num of filaments, always choose the map result that can be accommodated 2.In BestFit strategy,always try to fill up the existing capacity 3.In BestCost strategy, just try the group with fewest flush jira:NEW Signed-off-by: xun.zhang Change-Id: Ifd6d64b77774039e57ffff26cf2243a4d3f89054 --- src/libslic3r/FilamentGroup.cpp | 112 +++++++++++++++++---------- src/libslic3r/FilamentGroup.hpp | 16 ++-- src/libslic3r/GCode/ToolOrdering.cpp | 2 +- 3 files changed, 82 insertions(+), 48 deletions(-) diff --git a/src/libslic3r/FilamentGroup.cpp b/src/libslic3r/FilamentGroup.cpp index 9211385be..0f10bb953 100644 --- a/src/libslic3r/FilamentGroup.cpp +++ b/src/libslic3r/FilamentGroup.cpp @@ -3,7 +3,7 @@ namespace Slic3r { - int FilamentGroup::calc_filament_group(const std::vector>& layer_filaments) + int FilamentGroup::calc_filament_group(const std::vector>& layer_filaments,const FGStrategy& g_strategy) { std::setused_filaments; for (const auto& lf : layer_filaments) @@ -17,15 +17,15 @@ namespace Slic3r if (m_filament_num <= 1) return 0; if (m_filament_num < 10) - return calc_filament_group_by_enum(layer_filaments); + return calc_filament_group_by_enum(layer_filaments,g_strategy); else - return calc_filament_group_by_pam(layer_filaments,300); + return calc_filament_group_by_pam(layer_filaments,g_strategy,300); } - int FilamentGroup::calc_filament_group_by_enum(const std::vector>& layer_filaments) + int FilamentGroup::calc_filament_group_by_enum(const std::vector>& layer_filaments,const FGStrategy& g_strategy) { - auto bit_count_one = [](int n) + auto bit_count_one = [](uint64_t n) { int count = 0; while (n != 0) @@ -36,14 +36,26 @@ namespace Slic3r return count; }; + bool have_enough_size = (m_filament_num <= (m_max_group_size[0] + m_max_group_size[1])); + uint64_t max_group_num = static_cast(1 << m_filament_num); int best_cost = std::numeric_limits::max(); std::vectorbest_label; for (uint64_t i = 0; i < max_group_num; ++i) { int num_to_group_1 = bit_count_one(i); - if (num_to_group_1 > m_max_group_size[1] || (m_filament_num - num_to_group_1) > m_max_group_size[0]) + int num_to_group_0 = m_filament_num - num_to_group_1; + bool should_accept = false; + if (have_enough_size) + should_accept = (num_to_group_0 <= m_max_group_size[0] && num_to_group_1 <= m_max_group_size[1]); + else if (g_strategy == FGStrategy::BestCost) + should_accept = true; + else if (g_strategy == FGStrategy::BestFit) + should_accept = (num_to_group_0 >= m_max_group_size[0] && num_to_group_1 >= m_max_group_size[1]); + + if (!should_accept) continue; + std::setgroup_0, group_1; for (int j = 0; j < m_filament_num; ++j) { if (i & static_cast(1 << j)) @@ -52,29 +64,26 @@ namespace Slic3r group_0.insert(m_used_filaments[j]); } - if (group_0.size() < m_max_group_size[0] && group_1.size() < m_max_group_size[1]){ + std::vectorfilament_maps(m_filament_num); + for (int i = 0; i < m_filament_num; ++i) { + if (group_0.find(m_used_filaments[i]) != group_0.end()) + filament_maps[i] = 0; + if (group_1.find(m_used_filaments[i]) != group_1.end()) + filament_maps[i] = 1; + } - std::vectorfilament_maps(m_filament_num); - for (int i = 0; i < m_filament_num; ++i) { - if (group_0.find(m_used_filaments[i]) != group_0.end()) - filament_maps[i] = 0; - if (group_1.find(m_used_filaments[i]) != group_1.end()) - filament_maps[i] = 1; - } + int total_cost = reorder_filaments_for_minimum_flush_volume( + m_used_filaments, + filament_maps, + layer_filaments, + m_flush_matrix, + get_custom_seq, + nullptr + ); - int total_cost = reorder_filaments_for_minimum_flush_volume( - m_used_filaments, - filament_maps, - layer_filaments, - m_flush_matrix, - get_custom_seq, - nullptr - ); - - if (total_cost < best_cost) { - best_cost = total_cost; - best_label = filament_maps; - } + if (total_cost < best_cost) { + best_cost = total_cost; + best_label = filament_maps; } } @@ -83,7 +92,7 @@ namespace Slic3r return best_cost; } - int FilamentGroup::calc_filament_group_by_pam(const std::vector>& layer_filaments, int timeout_ms) + int FilamentGroup::calc_filament_group_by_pam(const std::vector>& layer_filaments,const FGStrategy& g_strategy, int timeout_ms) { //calc pair counts std::vector>count_matrix(m_filament_num,std::vector(m_filament_num)); @@ -116,7 +125,7 @@ namespace Slic3r } KMediods PAM(distance_matrix, m_filament_num,m_max_group_size); - PAM.fit(timeout_ms); + PAM.fit(g_strategy,timeout_ms); this->m_filament_labels = PAM.get_filament_labels(); int cost = reorder_filaments_for_minimum_flush_volume( @@ -132,7 +141,7 @@ namespace Slic3r } - void KMediods::fit( int timeout_ms) + void KMediods::fit(const FGStrategy&g_strategy , int timeout_ms) { std::vectorbest_medoids; std::vectorbest_labels; @@ -151,7 +160,7 @@ namespace Slic3r else medoids = initialize(INIT_TYPE::Random); - labels = assign_label(medoids); + labels = assign_label(medoids,g_strategy); int cost = calc_cost(labels, medoids); for (int i = 0; i < m_filament_num; ++i) { @@ -161,7 +170,7 @@ namespace Slic3r for (int j = 0; j < 2; ++j) { std::vector new_medoids = medoids; new_medoids[j] = i; - std::vector new_labels = assign_label(new_medoids); + std::vector new_labels = assign_label(new_medoids,g_strategy); int new_cost = calc_cost(new_labels, new_medoids); if (new_cost < cost) @@ -182,14 +191,14 @@ namespace Slic3r } count += 1; - if (T.time_machine_end() > timeout_ms) + if (T.time_machine_end() > timeout_ms || m_medoids_set.size() == (m_filament_num * (m_filament_num - 1) / 2)) break; } this->m_filament_labels = best_labels; } - std::vector KMediods::assign_label(const std::vector& medoids) const + std::vector KMediods::assign_label(const std::vector& medoids,const FGStrategy&g_strategy) const { std::vectorlabels(m_filament_num); struct Comp { @@ -205,15 +214,34 @@ namespace Slic3r min_heap.push({ i,distancec_to_0 - distancec_to_1 }); } std::set group_0, group_1; - while (!min_heap.empty()) { - auto top = min_heap.top(); - min_heap.pop(); - if (group_0.size() < m_max_group_size[0] && (top.second <= 0 || group_1.size() >= m_max_group_size[1])) - group_0.insert(top.first); - else - group_1.insert(top.first); - + bool have_enough_size = (m_filament_num <= (m_max_group_size[0] + m_max_group_size[1])); + if (have_enough_size || g_strategy == FGStrategy::BestFit) { + while (!min_heap.empty()) { + auto top = min_heap.top(); + min_heap.pop(); + if (group_0.size() < m_max_group_size[0] && (top.second <= 0 || group_1.size() >= m_max_group_size[1])) + group_0.insert(top.first); + else if (group_1.size() < m_max_group_size[1] && (top.second > 0 || group_0.size() >= m_max_group_size[0])) + group_1.insert(top.first); + else { + if (top.second <= 0) + group_0.insert(top.first); + else + group_1.insert(top.first); + } + } } + else if (g_strategy == FGStrategy::BestCost) { + while (!min_heap.empty()) { + auto top = min_heap.top(); + min_heap.pop(); + if (top.second <= 0) + group_0.insert(top.first); + else + group_1.insert(top.first); + } + } + for (auto& item : group_0) labels[item] = 0; for (auto& item : group_1) diff --git a/src/libslic3r/FilamentGroup.hpp b/src/libslic3r/FilamentGroup.hpp index 3d14094d5..37090347e 100644 --- a/src/libslic3r/FilamentGroup.hpp +++ b/src/libslic3r/FilamentGroup.hpp @@ -26,9 +26,15 @@ namespace Slic3r } }; + enum FGStrategy { + BestCost, + BestFit + }; class FilamentGroup { + public: + public: FilamentGroup(const std::vector& flush_matrix, const int filament_num, const std::vector& max_group_size) : m_flush_matrix{ flush_matrix }, @@ -36,9 +42,9 @@ namespace Slic3r m_max_group_size{ max_group_size } {} - int calc_filament_group(const std::vector>& layer_filaments); - int calc_filament_group_by_enum(const std::vector>& layer_filaments); - int calc_filament_group_by_pam(const std::vector>& layer_filaments, int timeout_ms = 300); + int calc_filament_group(const std::vector>& layer_filaments, const FGStrategy& g_strategy = FGStrategy::BestFit); + int calc_filament_group_by_enum(const std::vector>& layer_filaments,const FGStrategy& g_strategy); + int calc_filament_group_by_pam(const std::vector>& layer_filaments,const FGStrategy& g_strategy,int timeout_ms = 300); std::vector get_filament_map() const {return m_filament_labels;} @@ -68,14 +74,14 @@ namespace Slic3r m_filament_num{ filament_num }, m_max_group_size{ max_group_size } {} - void fit(int timeout_ms = 300); + void fit(const FGStrategy& g_strategy,int timeout_ms = 300); std::vectorget_filament_labels()const { return m_filament_labels; } private: std::vectorinitialize(INIT_TYPE type)const; - std::vectorassign_label(const std::vector& medoids)const; + std::vectorassign_label(const std::vector& medoids,const FGStrategy&g_strategy)const; int calc_cost(const std::vector& labels, const std::vector& medoids)const; private: std::vector>m_distance_matrix; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 68cb8cfaa..3a3fbf47c 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -1036,7 +1036,7 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vector