ENH: add wipe tower statistics in Gcodeviwer legend

Jira: new

Change-Id: Ic9b9f2ea9498d0cf36056288ef05d7e87cede165
This commit is contained in:
liz.li 2023-10-09 10:48:33 +08:00 committed by Lane.Wei
parent 39af8072ba
commit b02699e659

View File

@ -4170,14 +4170,24 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
float window_padding = 4.0f * m_scale;
const float icon_size = ImGui::GetTextLineHeight() * 0.7;
std::vector<float> offsets;
std::map<int, double> volume_of_extruders_all_plates; // map<extruder_idx, volume>
std::map<int, double> model_volume_of_extruders_all_plates; // map<extruder_idx, volume>
std::map<int, double> flushed_volume_of_extruders_all_plates; // map<extruder_idx, flushed volume>
std::map<int, double> wipe_tower_volume_of_extruders_all_plates; // map<extruder_idx, flushed volume>
std::vector<double> model_used_filaments_m_all_plates;
std::vector<double> model_used_filaments_g_all_plates;
std::vector<double> flushed_filaments_m_all_plates;
std::vector<double> flushed_filaments_g_all_plates;
std::vector<double> wipe_tower_used_filaments_m_all_plates;
std::vector<double> wipe_tower_used_filaments_g_all_plates;
float total_time_all_plates = 0.0f;
bool show_detailed_statistics_page = false;
struct ColumnData {
enum {
Model = 1,
Flushed = 2,
WipeTower = 4,
};
};
int displayed_columns = 0;
auto max_width = [](const std::vector<std::string>& items, const std::string& title, float extra_size = 0.0f) {
float ret = ImGui::CalcTextSize(title.c_str()).x;
@ -4258,32 +4268,49 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
for (size_t extruder_id : plate_extruders) {
extruder_id -= 1;
if (plate_print_statistics.volumes_per_extruder.find(extruder_id) == plate_print_statistics.volumes_per_extruder.end())
continue;
double volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
volume_of_extruders_all_plates[extruder_id] += volume;
flushed_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double model_volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
model_volume_of_extruders_all_plates[extruder_id] += model_volume;
}
if (plate_print_statistics.flush_per_filament.find(extruder_id) == plate_print_statistics.flush_per_filament.end())
flushed_volume_of_extruders_all_plates[extruder_id] = 0;
flushed_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double flushed_volume = plate_print_statistics.flush_per_filament.at(extruder_id);
flushed_volume_of_extruders_all_plates[extruder_id] += flushed_volume;
}
if (plate_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == plate_print_statistics.wipe_tower_volumes_per_extruder.end())
wipe_tower_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double wipe_tower_volume = plate_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id);
wipe_tower_volume_of_extruders_all_plates[extruder_id] += wipe_tower_volume;
}
}
const PrintEstimatedStatistics::Mode& plate_time_mode = plate_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
total_time_all_plates += plate_time_mode.time;
}
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
for (auto it = model_volume_of_extruders_all_plates.begin(); it != model_volume_of_extruders_all_plates.end(); it++) {
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (model_used_filament_m != 0.0 || model_used_filament_g != 0.0)
displayed_columns |= ColumnData::Model;
model_used_filaments_m_all_plates.push_back(model_used_filament_m);
model_used_filaments_g_all_plates.push_back(model_used_filament_g);
}
for (auto it = flushed_volume_of_extruders_all_plates.begin(); it != flushed_volume_of_extruders_all_plates.end(); it++) {
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (flushed_filament_m != 0.0 || flushed_filament_g != 0.0)
show_detailed_statistics_page = true;
displayed_columns |= ColumnData::Flushed;
flushed_filaments_m_all_plates.push_back(flushed_filament_m);
flushed_filaments_g_all_plates.push_back(flushed_filament_g);
}
for (auto it = wipe_tower_volume_of_extruders_all_plates.begin(); it != wipe_tower_volume_of_extruders_all_plates.end(); it++) {
auto [wipe_tower_filament_m, wipe_tower_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (wipe_tower_filament_m != 0.0 || wipe_tower_filament_g != 0.0)
displayed_columns |= ColumnData::WipeTower;
wipe_tower_used_filaments_m_all_plates.push_back(wipe_tower_filament_m);
wipe_tower_used_filaments_g_all_plates.push_back(wipe_tower_filament_g);
}
char buff[64];
double longest_str = 0.0;
@ -4292,25 +4319,40 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
longest_str = i;
}
::sprintf(buff, "%.2f", longest_str);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, /*{_u8L("Tower"), total_filaments},*/ {_u8L("Total"), {buff}} }, icon_size);
if (!show_detailed_statistics_page)
if (displayed_columns == ColumnData::Model) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]} });
else
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, /*{_u8L("Tower"), offsets[3]},*/ {_u8L("Total"), offsets[3]} });// to add Tower
}
else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} });
}
else {
if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower))
displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Tower"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} });
}
}
// item
{
size_t i = 0;
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
for (auto it = model_volume_of_extruders_all_plates.begin(); it != model_volume_of_extruders_all_plates.end(); it++) {
if (i < model_used_filaments_m_all_plates.size() && i < model_used_filaments_g_all_plates.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
char buf[64];
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0;
if (show_detailed_statistics_page) {
if (displayed_columns == ColumnData::Model) {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
@ -4321,9 +4363,19 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", wipe_tower_used_filaments_m_all_plates[i], wipe_tower_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i] + wipe_tower_used_filaments_m_all_plates[i]),
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i] + wipe_tower_used_filaments_g_all_plates[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[4] });
}
append_item(filament_colors[it->first], columns_offsets);
@ -4545,32 +4597,33 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
return ret;
};
auto color_print_ranges = [this](unsigned char extruder_id, const std::vector<CustomGCode::Item>& custom_gcode_per_print_z) {
std::vector<std::pair<Color, std::pair<double, double>>> ret;
ret.reserve(custom_gcode_per_print_z.size());
// BBS: no ColorChange type, use ToolChange
//auto color_print_ranges = [this](unsigned char extruder_id, const std::vector<CustomGCode::Item>& custom_gcode_per_print_z) {
// std::vector<std::pair<Color, std::pair<double, double>>> ret;
// ret.reserve(custom_gcode_per_print_z.size());
for (const auto& item : custom_gcode_per_print_z) {
if (extruder_id + 1 != static_cast<unsigned char>(item.extruder))
continue;
// for (const auto& item : custom_gcode_per_print_z) {
// if (extruder_id + 1 != static_cast<unsigned char>(item.extruder))
// continue;
if (item.type != ColorChange)
continue;
// if (item.type != ColorChange)
// continue;
const std::vector<double> zs = m_layers.get_zs();
auto lower_b = std::lower_bound(zs.begin(), zs.end(), item.print_z - epsilon());
if (lower_b == zs.end())
continue;
// const std::vector<double> zs = m_layers.get_zs();
// auto lower_b = std::lower_bound(zs.begin(), zs.end(), item.print_z - epsilon());
// if (lower_b == zs.end())
// continue;
const double current_z = *lower_b;
const double previous_z = (lower_b == zs.begin()) ? 0.0 : *(--lower_b);
// const double current_z = *lower_b;
// const double previous_z = (lower_b == zs.begin()) ? 0.0 : *(--lower_b);
// to avoid duplicate values, check adding values
if (ret.empty() || !(ret.back().second.first == previous_z && ret.back().second.second == current_z))
ret.push_back({ decode_color(item.color), { previous_z, current_z } });
}
// // to avoid duplicate values, check adding values
// if (ret.empty() || !(ret.back().second.first == previous_z && ret.back().second.second == current_z))
// ret.push_back({ decode_color(item.color), { previous_z, current_z } });
// }
return ret;
};
// return ret;
//};
auto upto_label = [](double z) {
char buf[64];
@ -4702,7 +4755,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
WipeTower = 4,
};
};
int displayed_columns = ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower;
int displayed_columns = 0;
const PrintStatistics& ps = wxGetApp().plater()->get_partplate_list().get_current_fff_print().print_statistics();
double koef = imperial_units ? GizmoObjectManipulation::in_to_mm : 1000.0;
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1;
@ -4782,40 +4835,52 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
case EViewType::ColorPrint:
{
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end()) continue;
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end()) {
model_used_filaments_m.push_back(0.0);
model_used_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
model_used_filaments_m.push_back(model_used_filament_m);
model_used_filaments_g.push_back(model_used_filament_g);
total_model_used_filament_m += model_used_filament_m;
total_model_used_filament_g += model_used_filament_g;
displayed_columns |= ColumnData::Model;
}
}
if (model_used_filaments_m.size() == 0 || model_used_filaments_g.size() == 0)
displayed_columns &= ~ColumnData::Model;
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == m_print_statistics.wipe_tower_volumes_per_extruder.end()) continue;
if (m_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == m_print_statistics.wipe_tower_volumes_per_extruder.end()) {
wipe_tower_used_filaments_m.push_back(0.0);
wipe_tower_used_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id);
auto [wipe_tower_used_filament_m, wipe_tower_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
wipe_tower_used_filaments_m.push_back(wipe_tower_used_filament_m);
wipe_tower_used_filaments_g.push_back(wipe_tower_used_filament_g);
total_wipe_tower_used_filament_m += wipe_tower_used_filament_m;
total_wipe_tower_used_filament_g += wipe_tower_used_filament_g;
displayed_columns |= ColumnData::WipeTower;
}
}
if (wipe_tower_used_filaments_m.size() == 0 || wipe_tower_used_filaments_g.size() == 0)
displayed_columns &= ~ColumnData::WipeTower;
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) continue;
if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) {
flushed_filaments_m.push_back(0.0);
flushed_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.flush_per_filament.at(extruder_id);
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, extruder_id);
flushed_filaments_m.push_back(flushed_filament_m);
flushed_filaments_g.push_back(flushed_filament_g);
total_flushed_filament_m += flushed_filament_m;
total_flushed_filament_g += flushed_filament_g;
displayed_columns |= ColumnData::Flushed;
}
}
if (flushed_filaments_m.size() == 0 || flushed_filaments_g.size() == 0)
displayed_columns &= ~ColumnData::Flushed;
std::vector<std::string> total_filaments;
char buffer[64];
@ -4827,34 +4892,14 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]}});
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
// add protection
assert(flushed_filaments_m.size() == model_used_filaments_m.size());
if (flushed_filaments_m.size() < model_used_filaments_m.size()) {
for (int i = 0; i < model_used_filaments_m.size() - flushed_filaments_m.size(); i++) {
flushed_filaments_m.push_back(std::nan("1"));
flushed_filaments_g.push_back(std::nan("1"));
}
}
else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} });
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) {
// add protection
assert(flushed_filaments_m.size() == model_used_filaments_m.size() == wipe_tower_used_filaments_m.size());
if (flushed_filaments_m.size() < model_used_filaments_m.size()) {
for (int i = 0; i < model_used_filaments_m.size() - flushed_filaments_m.size(); i++) {
flushed_filaments_m.push_back(std::nan("1"));
flushed_filaments_g.push_back(std::nan("1"));
}
}
if (wipe_tower_used_filaments_m.size() < model_used_filaments_m.size()) {
for (int i = 0; i < model_used_filaments_m.size() - wipe_tower_used_filaments_m.size(); i++) {
wipe_tower_used_filaments_m.push_back(std::nan("1"));
wipe_tower_used_filaments_g.push_back(std::nan("1"));
}
}
else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "displayed_columns: " << displayed_columns;
if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower))
displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Tower"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} });
@ -4979,51 +5024,20 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
//BBS: replace model custom gcode with current plate custom gcode
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes : m_custom_gcode_per_print_z;
size_t total_items = 1;
for (size_t extruder_id : m_extruder_ids) {
total_items += color_print_ranges(extruder_id, custom_gcode_per_print_z).size();
}
// BBS: no ColorChange type, use ToolChange
//for (size_t extruder_id : m_extruder_ids) {
// total_items += color_print_ranges(extruder_id, custom_gcode_per_print_z).size();
//}
const bool need_scrollable = static_cast<float>(total_items) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height;
// add scrollable region, if needed
if (need_scrollable)
ImGui::BeginChild("color_prints", { -1.0f, child_height }, false);
if (m_extruder_ids.size() == 1) { // single extruder use case
const std::vector<std::pair<Color, std::pair<double, double>>> cp_values = color_print_ranges(0, custom_gcode_per_print_z);
const int items_cnt = static_cast<int>(cp_values.size());
auto extruder_idx = m_extruder_ids[0];
if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0], model_used_filaments_g[0] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false);
}
else {
for (int i = items_cnt; i >= 0; --i) {
// create label for color change item
if (i == 0) {
append_item(EItemType::Rect, m_tools.m_tool_colors[0], {{ upto_label(cp_values.front().second.first), offsets[1]} }, false);
break;
}
else if (i == items_cnt) {
append_item(EItemType::Rect, cp_values[i - 1].first, { {above_label(cp_values[i - 1].second.second), offsets[1]} }, false);
continue;
}
append_item(EItemType::Rect, cp_values[i - 1].first, { {fromto_label(cp_values[i - 1].second.second, cp_values[i].second.first), offsets[1]} }, false);
}
}
}
else { // multi extruder use case
// shows only extruders actually used
size_t i = 0;
for (auto extruder_idx : m_extruder_ids) {
const std::vector<std::pair<Color, std::pair<double, double>>> cp_values = color_print_ranges(extruder_idx, custom_gcode_per_print_z);
const int items_cnt = static_cast<int>(cp_values.size());
if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode
const bool filament_visible = m_tools.m_tool_visibles[extruder_idx];
if (i < model_used_filaments_m.size() && i < model_used_filaments_g.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
@ -5070,29 +5084,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
}
}
else {
for (int j = items_cnt; j >= 0; --j) {
// create label for color change item
std::string label = _u8L("Filament") + " " + std::to_string(extruder_idx + 1);
if (j == 0) {
label += " " + upto_label(cp_values.front().second.first);
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], { { label, 0 } }, false);
break;
}
else if (j == items_cnt) {
label += " " + above_label(cp_values[j - 1].second.second);
append_item(EItemType::Rect, cp_values[j - 1].first, { { label, 0 } }, false);
continue;
}
label += " " + fromto_label(cp_values[j - 1].second.second, cp_values[j].second.first);
append_item(EItemType::Rect, cp_values[j - 1].first, { { label, 0 } }, false);
}
}
i++;
}
}
if (need_scrollable)
ImGui::EndChild();