add render base plugins

This commit is contained in:
2026-03-19 16:48:20 +03:00
parent 80d65e116e
commit e59fd990a1
6 changed files with 152 additions and 119 deletions

View File

@@ -28,6 +28,5 @@ namespace monitor::components
m_setup = setup; m_setup = setup;
m_graph.init(m_snapshot_id, m_setup); m_graph.init(m_snapshot_id, m_setup);
m_graph.set_plugin(m_base_plugins[0]); m_graph.set_plugin(m_base_plugins[0]);
m_graph.fill();
} }
} }

View File

@@ -14,7 +14,7 @@ namespace monitor::components
for (std::size_t i = 0; i < m_base_plugins.size(); ++i) for (std::size_t i = 0; i < m_base_plugins.size(); ++i)
{ {
ImGuiTabItemFlags flags = ImGuiTabItemFlags_NoCloseButton; 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; 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)) 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_current_open_index = i;
m_graph.set_plugin(m_base_plugins[i]); m_graph.set_plugin(m_base_plugins[i]);
m_graph.fill();
} }
} }
ImGui::EndTabBar(); ImGui::EndTabBar();
} }

View File

@@ -1,5 +1,4 @@
#include "monitor/gui/components/graph/graph.hpp" #include "monitor/gui/components/graph/graph.hpp"
#include "monitor/utils/var.hpp"
namespace monitor::components namespace monitor::components
{ {
@@ -26,10 +25,6 @@ namespace monitor::components
void graph::set_plugin(std::shared_ptr<utils::plugin> plugin) noexcept void graph::set_plugin(std::shared_ptr<utils::plugin> plugin) noexcept
{ {
m_plugin = std::move(plugin); m_plugin = std::move(plugin);
}
void graph::fill()
{
if (!m_plugin) hack::error()("The object is not installed"); if (!m_plugin) hack::error()("The object is not installed");
if (m_plugin->empty()) if (m_plugin->empty())
@@ -38,64 +33,36 @@ namespace monitor::components
{ {
case utils::plugin::TYPE::RAW_DATA: case utils::plugin::TYPE::RAW_DATA:
{ {
m_setup.m_domain = hr::DOMAIN_PLUGIN::TIME;
m_plugin->m_result = hr::run<hr::plugins::raw_data>(m_setup); m_plugin->m_result = hr::run<hr::plugins::raw_data>(m_setup);
m_total_size = m_plugin->m_result.size();
m_k = static_cast<float>(m_total_size) / utils::var::MAX_RENDER_SIZE;
downsampling();
break; break;
} }
case utils::plugin::TYPE::MAGNITUDE: case utils::plugin::TYPE::MAGNITUDE:
{ {
m_setup.m_domain = hr::DOMAIN_PLUGIN::FREQUENSY; m_setup.m_domain = hr::DOMAIN_PLUGIN::FREQUENSY;
m_plugin->m_result = hr::run<hr::plugins::magnitude>(m_setup); m_plugin->m_result = hr::run<hr::plugins::magnitude>(m_setup);
downsampling();
break; 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()("Пусто в расчетах!"); m_current_limits = current_limits;
hack::warn()("Нет данных для отрисовки, возможно что-то не так с плагином..."); m_plugin->fill(m_current_limits);
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);
} }
} }
} }

View File

@@ -18,12 +18,14 @@ namespace monitor::components
ImPlotAxisFlags_NoTickLabels // текстовые надписи отображаться не будут 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::SetupAxisLimits(ImAxis_Y1, 0.f, m_plugin->m_graph.m_max_element + 2.f);
ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 0, INFINITY); ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 0, INFINITY);
ImPlot::SetupLegend(ImPlotLocation_NorthEast); 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) 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()); 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()); 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; m_is_first_render = false;
ImPlot::EndPlot(); ImPlot::EndPlot();
} }

View File

@@ -20,22 +20,13 @@ namespace monitor::components
public: public:
void init(std::string snapshot_id, hr::setup setup); void init(std::string snapshot_id, hr::setup setup);
void set_plugin(std::shared_ptr<utils::plugin> plugin) noexcept; void set_plugin(std::shared_ptr<utils::plugin> plugin) noexcept;
void fill();
private: private:
void downsampling(); void refresh(ImPlotRect current_limits);
void refresh();
private: private:
std::shared_ptr<utils::plugin> m_plugin; std::shared_ptr<utils::plugin> m_plugin;
hr::setup m_setup; hr::setup m_setup;
std::string m_snapshot_id; std::string m_snapshot_id;
private:
// Общая длинна всех данных
std::size_t m_total_size;
// коеффициент того, на сколько данные больше возможного рендеринга
float m_k;
}; };
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <VE.hpp>
#include <harmonica.hpp> #include <harmonica.hpp>
#include "monitor/utils/var.hpp" #include "monitor/utils/var.hpp"
@@ -15,91 +16,172 @@ namespace monitor::utils
ENERGY ENERGY
}; };
struct graph_data public:
hr::result m_result;
TYPE m_type;
std::string m_display_name;
public:
struct graph
{ {
public: public:
// ось X // градуировка осьи X
hr::fvec_t m_ox; hr::fvec_t m_ox;
// максимальное значение по оси Y // максимальное значение по оси Y
double m_max_element = 0.0; double m_max_element = 0.0;
std::size_t m_line_count = 1; // размер данных дял отрисовки
// отличие этих данных от тех что в плагине: std::size_t m_size = 0;
// тут кол-во графиков на массив данных из этих графиков // кол-во линий графика
// т.е. std::size_t m_line_count = 0;
// [1] = [1, 2, ..., 1'000'000] // тут кол-во графиков на массив данных из этих графиков т.е.:
// [2] = [1, 2, ..., 1'000'000] // [1] = [1, 2, ..., 1'000'000'000]
// в плагине массив данных на кол-во графиков // [2] = [1, 2, ..., 1'000'000'000]
// [1] = [1, 2,...,7]
// [...] = [1, 2,...,7]
// [1'000'000] = [1, 2,...,7]
// потому как на рендеринг подается кол-во данных для одного графика сразу
std::vector<hr::fvec_t> m_data; std::vector<hr::fvec_t> 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); m_ox.clear();
for (std::size_t i = 0; i < var::MAX_RENDER_SIZE; ++i) m_ox.push_back(i); 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; } m_graph;
public:
hr::result m_result;
TYPE m_type;
const std::string m_display_name;
public: public:
bool empty() { return m_result.empty(); } bool empty() { return m_result.empty(); }
void base_fill() void graph_init()
{ {
// смотрим сколько линий на графике try
if (empty()) m_graph.m_line_count = m_result.m_data[0].m_value.size(); {
auto raw_size = m_result.size();
if (raw_size == 0) throw std::invalid_argument("Error set data in plugin: empty data");
// заполняем даннеы для всех линий графика m_graph.m_is_scale = raw_size > var::MAX_RENDER_SIZE;
for (std::size_t i = 0; i < m_graph.m_line_count; ++i) m_graph.m_size = std::min(raw_size, var::MAX_RENDER_SIZE);
m_graph.m_data.push_back(hr::fvec_t(var::MAX_RENDER_SIZE, 0.f)); m_graph.m_line_count = m_result.m_data.size();
m_graph.fill_ox(); m_graph.init();
m_graph.fill_ox();
}
catch(std::exception& e)
{
hack::error()(e.what());
}
} }
// этот метод запускается один раз при первом рендеринге
// для заполнения начальными данными
void fill() void fill()
{ {
// заполняется, когда данных пришло меньше чем нужно для полного рендеринга if (m_graph.m_is_scale)
// т.е. идем от пришедших данных. ниже наоборот от var::MAX_RENDER_SIZE
std::size_t index = 0;
for (auto el : m_result.m_data)
{ {
std::size_t graph_count = 0; m_step = m_result.size() / m_graph.m_size + 1;
for (auto e : el.m_value)
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); std::size_t index = 0;
m_graph.m_data[graph_count++][index] = e; 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 m_local_k2 = 0;
{ std::size_t m_step;
std::size_t step = k + 1;
std::size_t index = step;
std::size_t graph_count = 0;
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) for (auto& gd : m_graph.m_data)
{ {
std::size_t index = pos;
for (auto& g : gd) 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]; auto e = m_result.m_data[line_count][j].m_value;
g = hack::math::max_abs(e, g); // основной критерий сужения: берем максимальный элемент из данного интервала 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); g = tmp_e;
index += step; m_graph.m_max_element = std::fabs(hack::math::max_abs(g, m_graph.m_max_element));
if (index > m_result.m_data.size()) index = m_result.m_data.size();
index += m_step;
if (index > m_result.size()) index = m_result.size();
} }
++graph_count; ++line_count;
} }
// нужно передать смещение для установки градации
m_graph.fill_ox(skip_dots);
} }
}; };
} }