Added a 'layer statistics' legend for SLA

This commit is contained in:
Lukas Matena 2024-04-08 12:24:08 +02:00
parent 79ec60a049
commit 763c02f218
7 changed files with 81 additions and 20 deletions

View File

@ -412,7 +412,8 @@ struct SLAPrintStatistics
size_t fast_layers_count;
double total_cost;
double total_weight;
std::vector<double> layers_times;
std::vector<double> layers_times_running_total;
std::vector<double> layers_areas;
// Config with the filled in print statistics.
DynamicConfig config() const;
@ -429,7 +430,8 @@ struct SLAPrintStatistics
fast_layers_count = 0;
total_cost = 0.;
total_weight = 0.;
layers_times.clear();
layers_times_running_total.clear();
layers_areas.clear();
}
};

View File

@ -942,8 +942,10 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
double models_volume(0.0);
double estim_time(0.0);
std::vector<double> layers_times;
std::vector<std::pair<coord_t, double>> layers_times; // level and time
std::vector<std::pair<coord_t, double>> layers_areas; // level and area
layers_times.reserve(printer_input.size());
layers_areas.reserve(printer_input.size());
size_t slow_layers = 0;
size_t fast_layers = 0;
@ -961,7 +963,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
// write vars
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers,
&fast_layers, &fade_layer_time, &layers_times](size_t sliced_layer_cnt)
&fast_layers, &fade_layer_time, &layers_times, &layers_areas](size_t sliced_layer_cnt)
{
PrintLayer &layer = m_print->m_printer_input[sliced_layer_cnt];
@ -1029,6 +1031,8 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
Lock lck(mutex); supports_volume += layer_support_area * l_height;
}
double layer_area = layer_model_area + layer_support_area;
// Here we can save the expensively calculated polygons for printing
ExPolygons trslices;
trslices.reserve(model_polygons.size() + supports_polygons.size());
@ -1039,7 +1043,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
// Calculation of the slow and fast layers to the future controlling those values on FW
const bool is_fast_layer = (layer_model_area + layer_support_area) <= display_area*area_fill;
const bool is_fast_layer = layer_area <= display_area*area_fill;
const double tilt_time = material_config.material_print_speed == slamsSlow ? slow_tilt :
material_config.material_print_speed == slamsHighViscosity ? hv_tilt :
is_fast_layer ? fast_tilt : slow_tilt;
@ -1082,13 +1086,14 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
+ 120 / 1000 // Magical constant to compensate remaining computation delay in exposure thread
);
layers_times.push_back(layer_times);
layers_times.emplace_back(layer.level(), layer_times);
estim_time += layer_times;
layers_areas.emplace_back(layer.level(), layer_area * SCALING_FACTOR * SCALING_FACTOR);
}
};
// sequential version for debugging:
// for(size_t i = 0; i < m_printer_input.size(); ++i) printlayerfn(i);
// for(size_t i = 0; i < printer_input.size(); ++i) printlayerfn(i);
execution::for_each(ex_tbb, size_t(0), printer_input.size(), printlayerfn,
execution::max_concurrency(ex_tbb));
@ -1102,7 +1107,17 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
print_statistics.estimated_print_time = NaNd;
else {
print_statistics.estimated_print_time = estim_time;
print_statistics.layers_times = layers_times;
// Times and areas vectors were filled in parallel, they need to be sorted first.
// The print statistics will contain only the values (in the correct order).
std::sort(layers_times.begin(), layers_times.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
std::sort(layers_areas.begin(), layers_areas.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
print_statistics.layers_times_running_total.clear();
for (size_t i=0; i<layers_times.size(); ++i)
print_statistics.layers_times_running_total.emplace_back(layers_times[i].second + (i==0 ? 0. : print_statistics.layers_times_running_total[i-1]));
print_statistics.layers_areas.clear();
for (const auto& [level, area] : layers_areas)
print_statistics.layers_areas.emplace_back(area);
}
print_statistics.fast_layers_count = fast_layers;

View File

@ -6522,6 +6522,40 @@ void GLCanvas3D::_render_camera_target()
}
#endif // ENABLE_SHOW_CAMERA_TARGET
static void render_sla_layer_legend(const SLAPrint& print, int layer_idx, int cnv_width)
{
const std::vector<double>& areas = print.print_statistics().layers_areas;
const std::vector<double>& times = print.print_statistics().layers_times_running_total;
const double display_area = print.printer_config().display_height * print.printer_config().display_width;
if (layer_idx >= 0 && layer_idx < areas.size()) {
const double area = areas[layer_idx];
const double time = times[layer_idx] - (layer_idx == 0 ? 0. : times[layer_idx-1]);
const double time_until_layer = times[layer_idx];
ImGuiWrapper& imgui = *wxGetApp().imgui();
imgui.set_next_window_pos(float(cnv_width) - imgui.get_style_scaling() * 5.f, imgui.get_style_scaling() * 55.f, ImGuiCond_Always, 1.0f, 0.0f);
ImGui::SetNextWindowBgAlpha(0.6f);
imgui.begin(_u8L("Layer statistics"), ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoFocusOnAppearing);
ImGui::Text(_u8L("Layer area: %.0f mm²").c_str(), area);
int area_percent_int = int(std::round(100. * area/display_area));
ImGui::Text(GUI::format(_u8L("Area fill: %1% %%%%"), area_percent_int == 0 ? "<1" : std::to_string(area_percent_int)).c_str());
ImGui::Separator();
ImGui::Text(GUI::format(_u8L("Layer time: %1%"), get_time_dhms(time)).c_str());
std::string buffer_str = _u8L("Time since start: %1%");
ImGui::Text(GUI::format(buffer_str, get_time_dhms(time_until_layer)).c_str());
// The dummy control below uses the assumption that the total time string will be the longest
// and forces the width of the window large enough so it does not resize depending on the current value.
ImGui::Dummy(ImVec2(ImGui::CalcTextSize(GUI::format(buffer_str, get_time_dhms(82799)).c_str()).x, 0.));
imgui.end();
}
}
void GLCanvas3D::_render_sla_slices()
{
if (!m_use_clipping_planes || current_printer_technology() != ptSLA)
@ -6533,6 +6567,11 @@ void GLCanvas3D::_render_sla_slices()
// nothing to render, return
return;
if (print->finished()) {
double slider_width = 0.;
render_sla_layer_legend(*print, m_layer_slider_index, get_canvas_size().get_width());
}
double clip_min_z = -m_clipping_planes[0].get_data()[3];
double clip_max_z = m_clipping_planes[1].get_data()[3];
for (unsigned int i = 0; i < (unsigned int)print_objects.size(); ++i) {

View File

@ -504,6 +504,7 @@ private:
ClippingPlane m_camera_clipping_plane;
bool m_use_clipping_planes;
std::array<SlaCap, 2> m_sla_caps;
int m_layer_slider_index = -1;
std::string m_sidebar_field;
// when true renders an extra frame by not resetting m_dirty to false
// see request_extra_frame()
@ -757,6 +758,8 @@ public:
void bed_shape_changed();
void set_layer_slider_index(int i) { m_layer_slider_index = i; }
void set_clipping_plane(unsigned int id, const ClippingPlane& plane) {
if (id < 2) {
m_clipping_planes[id] = plane;

View File

@ -362,16 +362,6 @@ void Preview::sys_color_changed()
m_layers_slider->sys_color_changed();
}
void Preview::jump_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider) m_layers_slider->OnChar(evt);
}
void Preview::move_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider != nullptr) m_layers_slider->OnKeyDown(evt);
}
void Preview::edit_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider != nullptr) m_layers_slider->OnChar(evt);
@ -539,7 +529,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_layers_slider->SetDrawMode(sla_print_technology, sequential_print);
if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times);
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times_running_total);
else {
auto print_mode_stat = m_gcode_result->print_statistics.modes.front();
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
@ -907,6 +897,16 @@ void Preview::load_print_as_sla()
}
}
void Preview::jump_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider) m_layers_slider->OnChar(evt);
}
void Preview::move_layers_slider(wxKeyEvent& evt)
{
if (m_layers_slider != nullptr) m_layers_slider->OnKeyDown(evt);
}
void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event)
{
if (IsShown()) {
@ -919,6 +919,7 @@ void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event)
else if (tech == ptSLA) {
m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValueD()));
m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValueD()));
m_canvas->set_layer_slider_index(m_layers_slider->GetHigherValue());
m_canvas->render();
}
}

View File

@ -147,6 +147,7 @@ public:
void move_layers_slider(wxKeyEvent& evt);
void edit_layers_slider(wxKeyEvent& evt);
bool is_loaded() const { return m_loaded; }
void update_moves_slider();

View File

@ -5430,7 +5430,7 @@ void TabSLAMaterial::build_tilt_group(Slic3r::GUI::PageShp page)
create_legend(page, legend_columns, comExpert, true);
auto optgroup = page->new_optgroup(L("Tilt profiles"));
optgroup->on_change = [this, optgroup](const t_config_option_key& key, boost::any value)
optgroup->m_on_change = [this, optgroup](const t_config_option_key& key, boost::any value)
{
if (key.find_first_of("use_tilt") == 0)
toggle_tilt_options(key == "use_tilt#0");