diff options
| author | Paul Oliver <contact@pauloliver.dev> | 2026-06-16 02:58:15 +0200 |
|---|---|---|
| committer | Paul Oliver <contact@pauloliver.dev> | 2026-06-16 03:34:33 +0200 |
| commit | 279ad369ddf6f493c525b52237eb20560c7d55ae (patch) | |
| tree | 65da9dd15ae431fec4c29d23df3add19795a9045 | |
| parent | 06a6fec58d690905a6522c8e7d508c647350e88b (diff) | |
Client downsamples line plots automatically
| -rw-r--r-- | core/client.cpp | 62 | ||||
| -rw-r--r-- | core/server.c | 2 |
2 files changed, 57 insertions, 7 deletions
diff --git a/core/client.cpp b/core/client.cpp index ba0f3d6..cf85b27 100644 --- a/core/client.cpp +++ b/core/client.cpp @@ -342,6 +342,8 @@ std::vector<float> g_plot_cells_bottom; std::vector<bool> g_plots_covered; Plot *g_plot_selected; Plot *g_plot_hovered; +int g_plot_stride; +int g_downsampled_trace_len; int g_plot_cols = 2; size_t g_plot_col_selected; size_t g_plot_row_selected; @@ -538,11 +540,12 @@ void PlotLines::render_internal(const ImVec2 &frame_size) { (void)frame_size; ImS64 *x = g_trace_map[g_x_axes[g_x_axis]]->start(); + ImPlotSpec spec = ImPlotSpec(ImPlotProp_Stride, sizeof(ImS64) * g_plot_stride); for (auto &trace : m_trace_keys) { TraceNamed<ImS64> *trace_obj = g_trace_map[trace]; ImS64 *y = trace_obj->start(); - ImPlot::PlotLine(trace_obj->get_label(), x, y, g_trace_len); + ImPlot::PlotLine(trace_obj->get_label(), x, y, g_downsampled_trace_len, spec); } } @@ -636,12 +639,13 @@ void PlotStacked::render_internal(const ImVec2 &frame_size) { assert(m_trace_states[i] == GImPlot->CurrentPlot->Items.GetLegendItem(i)->Show); if (m_trace_states[i]) { - ImPlotSpec spec = ImPlotSpec(ImPlotProp_FillAlpha, GImPlot->CurrentPlot->Items.GetLegendItem(i)->LegendHovered ? 1.f : 0.9f); + bool hovered = GImPlot->CurrentPlot->Items.GetLegendItem(i)->LegendHovered; + ImPlotSpec spec = ImPlotSpec(ImPlotProp_FillAlpha, hovered ? 1.f : 0.9f, ImPlotProp_Stride, sizeof(double) * g_plot_stride); const char *trace_name = g_trace_map[m_trace_keys[i]]->get_label(); Trace<double> *current_trace = &m_trace_normals[i]; - ImPlot::PlotShaded(trace_name, g_x_axis_double.start(), prev_trace->start(), current_trace->start(), g_trace_len, spec); - ImPlot::PlotLine(trace_name, g_x_axis_double.start(), prev_trace->start(), g_trace_len); - ImPlot::PlotLine(trace_name, g_x_axis_double.start(), current_trace->start(), g_trace_len); + ImPlot::PlotShaded(trace_name, g_x_axis_double.start(), prev_trace->start(), current_trace->start(), g_downsampled_trace_len, spec); + ImPlot::PlotLine(trace_name, g_x_axis_double.start(), prev_trace->start(), g_downsampled_trace_len, spec); + if (hovered) ImPlot::PlotLine(trace_name, g_x_axis_double.start(), current_trace->start(), g_downsampled_trace_len, spec); prev_trace = current_trace; } } @@ -800,6 +804,30 @@ int64_t data_max_hm_pixel_pow(void) { return (int64_t)floor(log2((double)(MVEC_SIZE - g_hm_left) / (double)g_hm_pixel_count)); } +void data_update_stride(void) { + if (g_plot_maximized) { + g_plot_stride = 1; + g_downsampled_trace_len = g_trace_len; + return; + } + + int win_height = 0; + glfwGetWindowSize(g_window, nullptr, &win_height); + + int max_stride = g_plot_cols * ((win_height / (int)g_plot_height) + 1); + int max_points = DEFVAL_ENTRIES / max_stride; + g_plot_stride = 1; + + while (g_trace_len / g_plot_stride > max_points) { + g_plot_stride++; + } + + g_downsampled_trace_len = g_trace_len / g_plot_stride; + + log_info("Updated plot stride: %d", g_plot_stride); + log_info("Updated downsampled trace-len: %d", g_downsampled_trace_len); +} + void data_on_field_change(void) { g_entries = std::clamp(g_entries, 1l, DEFVAL_ENTRIES); g_nth = std::clamp(g_nth, DEFVAL_NTH, INT64_MAX); @@ -814,6 +842,8 @@ void data_on_field_change(void) { g_trace_len = 0l; g_trace_offset = 0;; + g_plot_stride = 0; + g_downsampled_trace_len = 0; for (auto &trace : g_traces) trace->clear(); for (auto &plot: g_plots) plot->flag_for_reset(); @@ -920,6 +950,7 @@ void data_fetch(void) { int64_t current_size = g_traces[0]->size(); g_trace_len = std::min(current_size, g_entries); g_trace_offset = current_size > g_entries ? current_size - g_entries : 0l; + data_update_stride(); mtx_unlock(&g_fetching_mutex); g_status = STATUS_RUNNING; @@ -1291,6 +1322,7 @@ void app_key_callback_plot_maximized(int key, int mods) { switch (key) { case GLFW_KEY_F: g_plot_maximized = false; + data_update_stride(); break; case GLFW_KEY_SPACE: app_toggle_state(); @@ -1334,18 +1366,22 @@ void app_key_callback(GLFWwindow* window, int key, int scancode, int action, int case GLFW_KEY_LEFT: g_plot_cols = std::max(g_plot_cols - 1, PLOT_MIN_COLS); data_reset_plot_cells(); + data_update_stride(); break; case GLFW_KEY_RIGHT: g_plot_cols = std::min(g_plot_cols + 1, PLOT_MAX_COLS); data_reset_plot_cells(); + data_update_stride(); break; case GLFW_KEY_UP: g_plot_height = std::min(g_plot_height + PLOT_HEIGHT_INTERVAL, PLOT_MAX_HEIGHT); gui_plot_queue_scroll_to_position(true); + data_update_stride(); break; case GLFW_KEY_DOWN: g_plot_height = std::max(g_plot_height - PLOT_HEIGHT_INTERVAL, PLOT_MIN_HEIGHT); gui_plot_queue_scroll_to_position(false); + data_update_stride(); break; } @@ -1372,7 +1408,11 @@ void app_key_callback(GLFWwindow* window, int key, int scancode, int action, int gui_plot_queue_scroll_to_selected(); break; case GLFW_KEY_F: - if (g_plot_selected->m_visible) g_plot_maximized = !g_plot_maximized; + if (g_plot_selected->m_visible) { + g_plot_maximized = !g_plot_maximized; + data_update_stride(); + } + break; case GLFW_KEY_SPACE: app_toggle_state(); @@ -1387,6 +1427,14 @@ void app_key_callback(GLFWwindow* window, int key, int scancode, int action, int } } +void app_window_size_callback(GLFWwindow* window, int width, int height) { + (void)window; + (void)width; + (void)height; + + data_update_stride(); +} + void app_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { (void)window; (void)mods; @@ -1416,6 +1464,7 @@ void init() { assert(g_window); glfwSetKeyCallback(g_window, app_key_callback); glfwSetMouseButtonCallback(g_window, app_mouse_button_callback); + glfwSetWindowSizeCallback(g_window, app_window_size_callback); glfwMakeContextCurrent(g_window); #if defined(VSYNC) glfwSwapInterval(1); @@ -1466,6 +1515,7 @@ void init() { g_plot_selected = g_plots[0]; g_hm_pixel_pow = data_max_hm_pixel_pow(); + data_update_stride(); mtx_init(&g_fetching_mutex, mtx_plain); } diff --git a/core/server.c b/core/server.c index 6b81178..82b6da5 100644 --- a/core/server.c +++ b/core/server.c @@ -162,7 +162,7 @@ void sql_callback_add_data(sqlite3_stmt *sql_stmt, void *data) { } callback_context->response_rows++; - log_info("Added row #%ld to callback context", callback_context->response_rows); + log_info("Processed row #%ld", callback_context->response_rows); free(render_contexts); free(threads); } |
