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 <xun.zhang@bambulab.com>
Change-Id: If54c4db79f33d5278c0f18d01ab0518e8660f9c7
This commit is contained in:
xun.zhang 2024-07-25 11:37:15 +08:00 committed by lane.wei
parent 0756b51eb2
commit 2dbc5c9396
6 changed files with 142 additions and 51 deletions

View File

@ -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<const PrintInstance*> print_object_instances_ordering;
std::vector<const PrintInstance*>::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<unsigned int>(-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.

View File

@ -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<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)
static FilamentChangeStats 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)
{
FilamentChangeStats ret;
std::map<int, int> flush_volume_per_filament;
std::vector<unsigned int>last_filament_per_extruder(2, -1);
int total_filament_change_count = 0;
@ -482,7 +482,10 @@ static std::pair<int,int> 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<int> ToolOrdering::get_recommended_filament_maps(const std::vector<s
return ret;
}
FilamentChangeStats ToolOrdering::get_filament_change_stats(FilamentChangeMode mode)
{
switch (mode)
{
case Slic3r::ToolOrdering::SingleExt:
return m_stats_by_single_extruder;
case Slic3r::ToolOrdering::MultiExtAuto:
return m_stats_by_multi_extruder_auto;
case Slic3r::ToolOrdering::MultiExtManual:
return m_stats_by_multi_extruder_manual;
default:
break;
}
return m_stats_by_single_extruder;
}
void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first_layer)
{
const PrintConfig* print_config = m_print_config_ptr;
@ -1283,9 +1302,11 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
}
std::vector<int>filament_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<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
// always calculate the info by one extruder
{
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;
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<std::vector<unsigned int>>filament_sequences_one_extruder;
std::vector<int>filament_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)

View File

@ -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<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; }
// should be called after doing reorder
FilamentChangeStats get_filament_change_stats(FilamentChangeMode mode);
private:
void initialize_layers(std::vector<coordf_t> &zs);
@ -234,8 +267,9 @@ private:
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 };
FilamentChangeStats m_stats_by_single_extruder;
FilamentChangeStats m_stats_by_multi_extruder_manual;
FilamentChangeStats m_stats_by_multi_extruder_auto;
};
} // namespace SLic3r

View File

@ -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<std::string, long long>* 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<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);
}
@ -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<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

@ -697,12 +697,14 @@ 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 };
// 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;

View File

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