#include "viz/bar_chart.h" #include "implot.h" #include namespace { // Render bars con ejes fijos y tamano de plot explicito. Dos cosas clave: // // 1) Limites pineados con ImPlotCond_Always + Lock: ImPlot por defecto // auto-fitea Y cada frame, lo que provoca oscilacion visual. // // 2) Altura explicita (height > 0 -> ImVec2(-1, height)): sin esto, ImPlot // toma el espacio disponible del contenedor. Si el contenedor es un // BeginChild con AutoResizeY (como dashboard_panel), aparece un feedback // loop: plot pide espacio al padre -> padre se redimensiona al plot -> // plot recalcula -> las barras "se deslizan" en los primeros frames. template void draw_bars(const char* title, const char* const* labels, const T* values, int count, double bar_width, float height) { if (count <= 0) return; double y_max = 0.0; for (int i = 0; i < count; i++) { if (static_cast(values[i]) > y_max) y_max = static_cast(values[i]); } if (y_max <= 0.0) y_max = 1.0; y_max *= 1.15; // 15% headroom sobre la barra mas alta const ImPlotFlags plot_flags = ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText | ImPlotFlags_NoInputs | ImPlotFlags_NoFrame; const ImPlotAxisFlags x_flags = ImPlotAxisFlags_NoMenus | ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoInitialFit | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight; const ImPlotAxisFlags y_flags = ImPlotAxisFlags_NoMenus | ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoInitialFit | ImPlotAxisFlags_NoHighlight; const ImVec2 plot_size(-1.0f, height > 0.0f ? height : 200.0f); if (ImPlot::BeginPlot(title, plot_size, plot_flags)) { std::vector positions(count); for (int i = 0; i < count; i++) positions[i] = i; ImPlot::SetupAxes(nullptr, nullptr, x_flags, y_flags); ImPlot::SetupAxisLimits(ImAxis_X1, -0.5, static_cast(count) - 0.5, ImPlotCond_Always); ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, y_max, ImPlotCond_Always); ImPlot::SetupAxisTicks(ImAxis_X1, positions.data(), count, labels); ImPlot::PlotBars("##data", values, count, bar_width); ImPlot::EndPlot(); } } } // namespace void bar_chart(const char* title, const char* const* labels, const float* values, int count, float bar_width, float height) { draw_bars(title, labels, values, count, static_cast(bar_width), height); } void bar_chart(const char* title, const char* const* labels, const double* values, int count, double bar_width, float height) { draw_bars(title, labels, values, count, bar_width, height); }