diff --git a/src/libslic3r/FilamentGroup.cpp b/src/libslic3r/FilamentGroup.cpp index cb1a8eac0..2a9b5b603 100644 --- a/src/libslic3r/FilamentGroup.cpp +++ b/src/libslic3r/FilamentGroup.cpp @@ -24,6 +24,19 @@ namespace Slic3r } } + static std::unordered_map get_merged_filament_map(const std::unordered_map>& merged_filaments) + { + std::unordered_map filament_merge_map; + for (auto elem : merged_filaments) { + for (auto f : elem.second) { + //traverse filaments in merged group + filament_merge_map[f] = elem.first; + } + } + return filament_merge_map; + } + + std::vector calc_filament_group_for_tpu(const std::set& tpu_filaments, const int filament_nums, const int master_extruder_id) { std::vector ret(filament_nums); @@ -129,8 +142,6 @@ namespace Slic3r { using namespace FlushPredict; - const double ams_color_dist_threshold = used_filaments.size() * color_threshold; - const int fail_cost = 9999; // these code is to make we machine filament info size is 2 @@ -189,14 +200,16 @@ namespace Slic3r auto ams_map = mcmf.solve(); for (size_t idx = 0; idx < ams_map.size(); ++idx) { - if (ams_map[idx] == MaxFlowGraph::INVALID_ID) + if (ams_map[idx] == MaxFlowGraph::INVALID_ID || distance_matrix[idx][ams_map[idx]] > color_threshold) { group_cost += fail_cost; - else + } + else { group_cost += distance_matrix[idx][ams_map[idx]]; + } } } - if (best_map.empty() || (group_cost < ams_color_dist_threshold && group_cost < best_cost)) { + if (best_map.empty() || group_cost < best_cost) { best_cost = group_cost; best_map = map; } @@ -479,6 +492,88 @@ namespace Slic3r return calc_min_flush_group_by_pam2(used_filaments, cost, 500); } + std::unordered_map> FilamentGroup::try_merge_filaments() + { + std::unordered_map>merged_filaments; + + std::unordered_map> merge_filament_map; + + auto unprintable_stat_to_str = [unprintable_filaments = this->ctx.model_info.unprintable_filaments](int idx) { + std::string str; + for (size_t eid = 0; eid < unprintable_filaments.size(); ++eid) { + if (unprintable_filaments[eid].count(idx)) { + if (eid > 0) + str += ','; + str += std::to_string(idx); + } + } + return str; + }; + + for (size_t idx = 0; idx < ctx.model_info.filament_ids.size(); ++idx) { + std::string id = ctx.model_info.filament_ids[idx]; + Color color = ctx.model_info.filament_info[idx].color; + std::string unprintable_str = unprintable_stat_to_str(idx); + + std::string key = id + "," + color.to_hex_str(true) + "," + unprintable_str; + merge_filament_map[key].push_back(idx); + } + + for (auto& elem : merge_filament_map) { + if (elem.second.size() > 1) { + merged_filaments[elem.second.front()] = elem.second; + } + } + return merged_filaments; + } + + std::vector FilamentGroup::seperate_merged_filaments(const std::vector& filament_map, const std::unordered_map>& merged_filaments) + { + std::vector ret_map = filament_map; + for (auto& elem : merged_filaments) { + int src = elem.first; + for (auto f : elem.second) { + ret_map[f] = ret_map[src]; + } + } + return ret_map; + } + + void FilamentGroup::rebuild_context(const std::unordered_map>& merged_filaments) + { + if (merged_filaments.empty()) + return; + + FilamentGroupContext new_ctx = ctx; + + std::unordered_map filament_merge_map = get_merged_filament_map(merged_filaments); + + // modify layer filaments + for (auto& layer_filament : new_ctx.model_info.layer_filaments) { + for (auto& f : layer_filament) { + if (auto iter = filament_merge_map.find((int)(f)); iter != filament_merge_map.end()) { + f = iter->second; + } + } + } + + for (auto& unprintables : new_ctx.model_info.unprintable_filaments) { + std::set new_unprintables; + for (auto f : unprintables) { + if (auto iter = filament_merge_map.find((int)(f)); iter != filament_merge_map.end()) { + new_unprintables.insert(iter->second); + } + else { + new_unprintables.insert(f); + } + } + } + + ctx = new_ctx; + return; + } + + std::vector FilamentGroup::calc_filament_group(int* cost) { @@ -488,7 +583,11 @@ namespace Slic3r } catch (const FilamentGroupException& e) { } - return calc_filament_group_for_flush(cost); + + auto merged_map = try_merge_filaments(); + rebuild_context(merged_map); + auto filamnet_map = calc_filament_group_for_flush(cost); + return seperate_merged_filaments(filamnet_map, merged_map); } std::vector FilamentGroup::calc_filament_group_for_match(int* cost) @@ -529,16 +628,7 @@ namespace Slic3r std::iota(l_nodes.begin(), l_nodes.end(), 0); std::vectorr_nodes(machine_filament_list.size()); std::iota(r_nodes.begin(), r_nodes.end(), 0); - std::vectormachine_filament_capacity(machine_filament_list.size()); - for (size_t idx = 0; idx < machine_filament_capacity.size(); ++idx) { - if (machine_filament_list[idx].is_extended) { - machine_filament_capacity[idx] = 1; // extend filaments can at most map one filaments - } - else { - machine_filament_capacity[idx] = l_nodes.size(); // AMS filaments can map multiple filaments - } - } - + std::vectormachine_filament_capacity(machine_filament_list.size(),l_nodes.size()); std::vectorextruder_filament_count(2, 0); auto is_extruder_filament_compatible = [&unprintable_limit_indices](int filament_idx, int extruder_id) { @@ -628,19 +718,7 @@ namespace Slic3r { MatchModeGroupSolver s(color_dist_matrix, l_nodes, r_nodes, machine_filament_capacity, unlink_limits_full); - ungrouped_filaments = optimize_map_to_machine_filament(s.solve(), l_nodes, r_nodes,group,true); - if (ungrouped_filaments.empty()) - return group; - } - - for (size_t idx = 0; idx < machine_filament_capacity.size(); ++idx) - machine_filament_capacity[idx] = l_nodes.size(); - - // remove capacity limits - { - l_nodes = ungrouped_filaments; - MatchModeGroupSolver s(color_dist_matrix, l_nodes, r_nodes, machine_filament_capacity, unlink_limits_full); - ungrouped_filaments = optimize_map_to_machine_filament(s.solve(), l_nodes, r_nodes, group,false); + ungrouped_filaments = optimize_map_to_machine_filament(s.solve(), l_nodes, r_nodes,group,false); if (ungrouped_filaments.empty()) return group; } diff --git a/src/libslic3r/FilamentGroup.hpp b/src/libslic3r/FilamentGroup.hpp index 646e98c0c..ce1aedfbb 100644 --- a/src/libslic3r/FilamentGroup.hpp +++ b/src/libslic3r/FilamentGroup.hpp @@ -73,6 +73,7 @@ namespace Slic3r std::vector flush_matrix; std::vector> layer_filaments; std::vector filament_info; + std::vector filament_ids; std::vector> unprintable_filaments; } model_info; @@ -133,6 +134,11 @@ namespace Slic3r std::vector calc_min_flush_group(int* cost = nullptr); std::vector calc_min_flush_group_by_enum(const std::vector& used_filaments, int* cost = nullptr); std::vector calc_min_flush_group_by_pam2(const std::vector& used_filaments, int* cost = nullptr, int timeout_ms = 300); + + std::unordered_map> try_merge_filaments(); + void rebuild_context(const std::unordered_map>& merged_filaments); + std::vector seperate_merged_filaments(const std::vector& filament_map, const std::unordered_map>& merged_filaments ); + private: FilamentGroupContext ctx; std::vector> m_memoryed_groups; diff --git a/src/libslic3r/FilamentGroupUtils.cpp b/src/libslic3r/FilamentGroupUtils.cpp index 309cd5e85..6089ac24b 100644 --- a/src/libslic3r/FilamentGroupUtils.cpp +++ b/src/libslic3r/FilamentGroupUtils.cpp @@ -1,5 +1,5 @@ #include "FilamentGroupUtils.hpp" - +#include namespace Slic3r { @@ -45,6 +45,20 @@ namespace FilamentGroupUtils return r != other.r || g != other.g || b != other.b || a != other.a; } + std::string Color::to_hex_str(bool include_alpha) const { + std::ostringstream oss; + oss << "#" << std::hex << std::setfill('0') + << std::setw(2) << static_cast(r) + << std::setw(2) << static_cast(g) + << std::setw(2) << static_cast(b); + + if (include_alpha) { + oss << std::setw(2) << static_cast(a); + } + return oss.str(); + } + + bool MachineFilamentInfo::operator<(const MachineFilamentInfo& other) const { if (color != other.color) return color < other.color; diff --git a/src/libslic3r/FilamentGroupUtils.hpp b/src/libslic3r/FilamentGroupUtils.hpp index b42de01a0..71839c2be 100644 --- a/src/libslic3r/FilamentGroupUtils.hpp +++ b/src/libslic3r/FilamentGroupUtils.hpp @@ -23,6 +23,7 @@ namespace Slic3r bool operator<(const Color& other) const; bool operator==(const Color& other) const; bool operator!=(const Color& other) const; + std::string to_hex_str(bool include_alpha = false) const; }; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index a9af4a01d..4332f536b 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -1008,7 +1008,7 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vector filament_types = print_config.filament_type.values; std::vector filament_colours = print_config.filament_colour.values; std::vector filament_is_support = print_config.filament_is_support.values; - + std::vector filament_ids = print_config.filament_ids.values; // speacially handle tpu filaments auto used_filaments = collect_sorted_used_filaments(layer_filaments); auto tpu_filaments = get_filament_by_type(used_filaments, &print_config, "TPU"); @@ -1022,6 +1022,7 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vector