From e59fd990a1839efe457146c6d7dbe86de64eb617 Mon Sep 17 00:00:00 2001 From: chatlanin Date: Thu, 19 Mar 2026 16:48:20 +0300 Subject: [PATCH] add render base plugins --- .../gui/components/base_plugins/cpp/base.cpp | 1 - .../components/base_plugins/cpp/render.cpp | 4 +- src/monitor/gui/components/graph/cpp/base.cpp | 63 ++---- .../gui/components/graph/cpp/render.cpp | 12 +- src/monitor/gui/components/graph/graph.hpp | 11 +- src/monitor/utils/plugin.hpp | 180 +++++++++++++----- 6 files changed, 152 insertions(+), 119 deletions(-) diff --git a/src/monitor/gui/components/base_plugins/cpp/base.cpp b/src/monitor/gui/components/base_plugins/cpp/base.cpp index 7952aae..fa7567c 100644 --- a/src/monitor/gui/components/base_plugins/cpp/base.cpp +++ b/src/monitor/gui/components/base_plugins/cpp/base.cpp @@ -28,6 +28,5 @@ namespace monitor::components m_setup = setup; m_graph.init(m_snapshot_id, m_setup); m_graph.set_plugin(m_base_plugins[0]); - m_graph.fill(); } } diff --git a/src/monitor/gui/components/base_plugins/cpp/render.cpp b/src/monitor/gui/components/base_plugins/cpp/render.cpp index 8a4908c..dbeda58 100644 --- a/src/monitor/gui/components/base_plugins/cpp/render.cpp +++ b/src/monitor/gui/components/base_plugins/cpp/render.cpp @@ -14,7 +14,7 @@ namespace monitor::components for (std::size_t i = 0; i < m_base_plugins.size(); ++i) { ImGuiTabItemFlags flags = ImGuiTabItemFlags_NoCloseButton; - // if (m_current_open_index == i) flags |= ImGuiTabItemFlags_SetSelected; // Добавляем флаг выделения если нужно + if (m_current_open_index == i) flags |= ImGuiTabItemFlags_SetSelected; // Добавляем флаг выделения если нужно bool open = true; if (ImGui::BeginTabItem(("[ " + std::to_string(i + 1) + " ] " + utils::func::string_cut(m_base_plugins[i]->m_display_name, 30)).c_str(), &open, flags)) { @@ -26,10 +26,8 @@ namespace monitor::components { m_current_open_index = i; m_graph.set_plugin(m_base_plugins[i]); - m_graph.fill(); } } - ImGui::EndTabBar(); } diff --git a/src/monitor/gui/components/graph/cpp/base.cpp b/src/monitor/gui/components/graph/cpp/base.cpp index 62def73..a33775c 100755 --- a/src/monitor/gui/components/graph/cpp/base.cpp +++ b/src/monitor/gui/components/graph/cpp/base.cpp @@ -1,5 +1,4 @@ #include "monitor/gui/components/graph/graph.hpp" -#include "monitor/utils/var.hpp" namespace monitor::components { @@ -26,10 +25,6 @@ namespace monitor::components void graph::set_plugin(std::shared_ptr plugin) noexcept { m_plugin = std::move(plugin); - } - - void graph::fill() - { if (!m_plugin) hack::error()("The object is not installed"); if (m_plugin->empty()) @@ -38,64 +33,36 @@ namespace monitor::components { case utils::plugin::TYPE::RAW_DATA: { + m_setup.m_domain = hr::DOMAIN_PLUGIN::TIME; m_plugin->m_result = hr::run(m_setup); - m_total_size = m_plugin->m_result.size(); - m_k = static_cast(m_total_size) / utils::var::MAX_RENDER_SIZE; - downsampling(); break; } case utils::plugin::TYPE::MAGNITUDE: { m_setup.m_domain = hr::DOMAIN_PLUGIN::FREQUENSY; m_plugin->m_result = hr::run(m_setup); - downsampling(); break; } } + if (!m_plugin->empty()) + { + m_plugin->graph_init(); + m_plugin->fill(); + } + else + { + hack::error()("NOT SET RAW DATA!"); + } } } - void graph::downsampling() + void graph::refresh(ImPlotRect current_limits) { - if (m_total_size == 0) + if (!m_plugin->is_scale()) return; + if (m_current_limits.Min().x != current_limits.Min().x) { - hack::error()("Пусто в расчетах!"); - hack::warn()("Нет данных для отрисовки, возможно что-то не так с плагином..."); - return; - } - - m_plugin->base_fill(); - if (m_k > 1.f) m_plugin->fill(m_k); - else m_plugin->fill(); - } - - void graph::refresh() - { - auto k = m_plugin->m_result.size() / m_current_limits.Size().x; - hack::log()(k, m_plugin->m_result.size(), m_k, m_current_limits.X.Min, m_current_limits.X.Max); - if (k > 70.f && k < 80.f) - { - m_plugin->fill(m_k - 3); - } - if (k > 100.f && k < 110.f) - { - m_plugin->fill(m_k - 4); - } - if (k > 150.f && k < 160.f) - { - m_plugin->fill(m_k - 5); - } - if (k > 190.f && k < 200.f) - { - m_plugin->fill(m_k - 6); - } - if (k > 250.f && k < 300.f) - { - m_plugin->fill(m_k - 7); - } - if (k > 310.f && k < 1'000) - { - m_plugin->fill(0.f); + m_current_limits = current_limits; + m_plugin->fill(m_current_limits); } } } diff --git a/src/monitor/gui/components/graph/cpp/render.cpp b/src/monitor/gui/components/graph/cpp/render.cpp index a775661..b6899a3 100755 --- a/src/monitor/gui/components/graph/cpp/render.cpp +++ b/src/monitor/gui/components/graph/cpp/render.cpp @@ -18,12 +18,14 @@ namespace monitor::components ImPlotAxisFlags_NoTickLabels // текстовые надписи отображаться не будут ); - ImPlot::SetupAxisLimits(ImAxis_X1, 0.f, m_plugin->m_graph.m_data.size()); + ImPlot::SetupAxisLimits(ImAxis_X1, 0.f, m_plugin->m_graph.m_size); ImPlot::SetupAxisLimits(ImAxis_Y1, 0.f, m_plugin->m_graph.m_max_element + 2.f); ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 0, INFINITY); ImPlot::SetupLegend(ImPlotLocation_NorthEast); - for (std::size_t i = 0; i < m_plugin->m_graph.m_data.size(); ++i) + refresh(ImPlot::GetPlotLimits()); + + for (std::size_t i = 0; i < m_plugin->m_graph.m_line_count; ++i) { if (m_plugin->m_type == utils::plugin::TYPE::ENERGY) ImPlot::PlotStems(VE_NAME(std::to_string(i)), m_plugin->m_graph.m_ox.data(), m_plugin->m_graph.m_data[i].data(), m_plugin->m_graph.m_data[i].size()); @@ -31,12 +33,6 @@ namespace monitor::components ImPlot::PlotLine(VE_NAME(std::to_string(i)), m_plugin->m_graph.m_ox.data(), m_plugin->m_graph.m_data[i].data(), m_plugin->m_graph.m_data[i].size()); } - if (m_k > 1.f) - { - m_current_limits = ImPlot::GetPlotLimits(); - refresh(); - } - m_is_first_render = false; ImPlot::EndPlot(); } diff --git a/src/monitor/gui/components/graph/graph.hpp b/src/monitor/gui/components/graph/graph.hpp index 47365f5..248730f 100755 --- a/src/monitor/gui/components/graph/graph.hpp +++ b/src/monitor/gui/components/graph/graph.hpp @@ -20,22 +20,13 @@ namespace monitor::components public: void init(std::string snapshot_id, hr::setup setup); void set_plugin(std::shared_ptr plugin) noexcept; - void fill(); private: - void downsampling(); - void refresh(); + void refresh(ImPlotRect current_limits); private: std::shared_ptr m_plugin; hr::setup m_setup; std::string m_snapshot_id; - - private: - // Общая длинна всех данных - std::size_t m_total_size; - // коеффициент того, на сколько данные больше возможного рендеринга - float m_k; - }; } diff --git a/src/monitor/utils/plugin.hpp b/src/monitor/utils/plugin.hpp index 686d680..74e57c3 100644 --- a/src/monitor/utils/plugin.hpp +++ b/src/monitor/utils/plugin.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "monitor/utils/var.hpp" @@ -15,91 +16,172 @@ namespace monitor::utils ENERGY }; - struct graph_data + public: + hr::result m_result; + TYPE m_type; + std::string m_display_name; + + public: + struct graph { public: - // ось X + // градуировка осьи X hr::fvec_t m_ox; // максимальное значение по оси Y double m_max_element = 0.0; - std::size_t m_line_count = 1; - // отличие этих данных от тех что в плагине: - // тут кол-во графиков на массив данных из этих графиков - // т.е. - // [1] = [1, 2, ..., 1'000'000] - // [2] = [1, 2, ..., 1'000'000] - // в плагине массив данных на кол-во графиков - // [1] = [1, 2,...,7] - // [...] = [1, 2,...,7] - // [1'000'000] = [1, 2,...,7] - // потому как на рендеринг подается кол-во данных для одного графика сразу + // размер данных дял отрисовки + std::size_t m_size = 0; + // кол-во линий графика + std::size_t m_line_count = 0; + // тут кол-во графиков на массив данных из этих графиков т.е.: + // [1] = [1, 2, ..., 1'000'000'000] + // [2] = [1, 2, ..., 1'000'000'000] std::vector m_data; + // говорит нужно ли делать сжатие графика ли нет + bool m_is_scale = false; - void fill_ox() noexcept + void fill_ox(std::size_t start_pos = 0) { - m_ox.reserve(var::MAX_RENDER_SIZE); - for (std::size_t i = 0; i < var::MAX_RENDER_SIZE; ++i) m_ox.push_back(i); + m_ox.clear(); + for (std::size_t i = start_pos; i < start_pos + m_size; ++i) m_ox.push_back(i); + } + + void init() + { + m_data.reserve(m_line_count); + m_ox.reserve(m_size); + for (std::size_t i = 0; i < m_line_count; ++i) m_data.push_back(hr::fvec_t(m_size, 0.f)); } } m_graph; - public: - hr::result m_result; - TYPE m_type; - const std::string m_display_name; - public: bool empty() { return m_result.empty(); } - void base_fill() + void graph_init() { - // смотрим сколько линий на графике - if (empty()) m_graph.m_line_count = m_result.m_data[0].m_value.size(); + try + { + auto raw_size = m_result.size(); + if (raw_size == 0) throw std::invalid_argument("Error set data in plugin: empty data"); - // заполняем даннеы для всех линий графика - for (std::size_t i = 0; i < m_graph.m_line_count; ++i) - m_graph.m_data.push_back(hr::fvec_t(var::MAX_RENDER_SIZE, 0.f)); - m_graph.fill_ox(); + m_graph.m_is_scale = raw_size > var::MAX_RENDER_SIZE; + m_graph.m_size = std::min(raw_size, var::MAX_RENDER_SIZE); + m_graph.m_line_count = m_result.m_data.size(); + m_graph.init(); + m_graph.fill_ox(); + } + catch(std::exception& e) + { + hack::error()(e.what()); + } } + // этот метод запускается один раз при первом рендеринге + // для заполнения начальными данными void fill() { - // заполняется, когда данных пришло меньше чем нужно для полного рендеринга - // т.е. идем от пришедших данных. ниже наоборот от var::MAX_RENDER_SIZE - std::size_t index = 0; - for (auto el : m_result.m_data) + if (m_graph.m_is_scale) { - std::size_t graph_count = 0; - for (auto e : el.m_value) + m_step = m_result.size() / m_graph.m_size + 1; + + std::size_t line_count = 0; + for (auto& gd : m_graph.m_data) { - m_graph.m_max_element = hack::math::max(e, m_graph.m_max_element); - m_graph.m_data[graph_count++][index] = e; + std::size_t index = 0; + for (auto& g : gd) + { + float tmp_e = 0.f; + for (std::size_t j = index - m_step; j < index; ++j) + { + auto e = m_result.m_data[line_count][j].m_value; + tmp_e = hack::math::max_abs(e, tmp_e); + } + g = tmp_e; + m_graph.m_max_element = std::fabs(hack::math::max_abs(g, m_graph.m_max_element)); + + index += m_step; + if (index > m_result.size()) index = m_result.size(); + } + ++line_count; + } + } + else + { + // заполняется, когда данных пришло меньше чем нужно для полного рендеринга + std::size_t graph_count = 0; + for (auto el : m_result.m_data) + { + std::size_t index = 0; + for (auto e : el) + { + m_graph.m_max_element = hack::math::max(e.m_value, m_graph.m_max_element); + m_graph.m_data[graph_count][index] = e.m_value; + ++index; + } + ++graph_count; } - ++index; } } - void fill(float k) - { - std::size_t step = k + 1; - std::size_t index = step; - std::size_t graph_count = 0; + std::size_t m_local_k2 = 0; + std::size_t m_step; + bool is_scale() + { + return m_graph.m_is_scale; + } + + // Это основной меод вычисления данных, которые нужно отрисовать + // 1. Проверяем размер сырых данных + // - если их больше чем var::MAX_RENDER_SIZE, то делаем сжатие + // - если их меньше, то отрисовка идет полностью и fill_ox уже заполнен так как надо и при масштабировании ни чего не пересчитывается is_scale + void fill(ImPlotRect current_limits) + { + // кол-во данных, которые мы сейчас хотим отрисовать, когда поменяли масштаб + auto total_dots_for_render = current_limits.Size().x; + // тоже, что начальный m_step, но если m_step меняется, то этот постоянный + // т.е. это максимальный коефиниент сужения графика + std::size_t k1 = m_result.size() / m_graph.m_size + 1; + // на сколько изменилось кол-во точек, которые нужно отрисовать + std::size_t k2 = var::MAX_RENDER_SIZE / total_dots_for_render - 1.f; + + // стэк условий, котолрые ограничивают лишние расчеты и сохраняют текущие данные + if (k1 <= k2 && k2 != 0) return; + if (m_local_k2 == k2 && k2 != 0) return; + m_local_k2 = k2; + + // сколько сместилось точке отрисовки во время масштабирования за экран (влево) + std::size_t skip_dots = current_limits.Min().x; + // кол-во точек, которые нужно пропустить из сырых данных чтобы они не были отрисованы во время масштабирования + std::size_t pos = skip_dots * (m_step + k2); + // шаг пропуска, по которому делаем сужение графика + m_step = k1 - k2; + + std::size_t line_count = 0; for (auto& gd : m_graph.m_data) { + std::size_t index = pos; for (auto& g : gd) { - for (std::size_t j = index - step; j < index; ++j) + float tmp_e = 0.f; + for (std::size_t j = index - m_step; j < index; ++j) { - auto e = m_result.m_data[j].m_value[graph_count]; - g = hack::math::max_abs(e, g); + auto e = m_result.m_data[line_count][j].m_value; + // основной критерий сужения: берем максимальный элемент из данного интервала m_step + tmp_e = hack::math::max_abs(e, tmp_e); } - m_graph.m_max_element = hack::math::max(g, m_graph.m_max_element); - index += step; - if (index > m_result.m_data.size()) index = m_result.m_data.size(); + g = tmp_e; + m_graph.m_max_element = std::fabs(hack::math::max_abs(g, m_graph.m_max_element)); + + index += m_step; + if (index > m_result.size()) index = m_result.size(); } - ++graph_count; + ++line_count; } + + // нужно передать смещение для установки градации + m_graph.fill_ox(skip_dots); } }; }