mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 00:36:25 +08:00
Added a 'layer statistics' legend for SLA
This commit is contained in:
parent
79ec60a049
commit
763c02f218
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user