Files
fn_registry/cpp/functions/viz/gauge.cpp
T
egutierrez 0bdf35a461 feat: add C++ ImGui functions for core UI and visualization
Funciones C++/ImGui para dashboards (grid, panel, docking, sidebar, tabs),
visualizaciones (candlestick, gauge, histogram, pie, sparkline, heatmap,
scatter, line, bar, surface3d, kpi, table), grafos (force layout, renderer,
viewport, spatial hash, types) y utilidades (time series buffer, tracy zones,
memory/fps overlay, plot theme).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 00:10:18 +02:00

95 lines
3.5 KiB
C++

#include "viz/gauge.h"
#include "imgui.h"
#include <cmath>
#include <cstdio>
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
void gauge(const char* label, float value, float min_val, float max_val, float radius) {
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImVec2 pos = ImGui::GetCursorScreenPos();
// Reserve space: diameter + label line
float diameter = radius * 2.0f;
ImGui::Dummy(ImVec2(diameter, diameter + ImGui::GetTextLineHeightWithSpacing()));
ImVec2 center = ImVec2(pos.x + radius, pos.y + radius);
// Arc spans 240 degrees: from 150deg to 390deg (i.e. 150 to 30 going clockwise)
// In screen space Y is down, so angles go clockwise.
// Start angle: 150 degrees = bottom-left, End angle: 390 = 30 degrees = bottom-right
const float angle_start = (150.0f * (float)M_PI) / 180.0f;
const float angle_end = (390.0f * (float)M_PI) / 180.0f;
const int num_segments = 64;
// Background arc (dark gray)
ImU32 bg_color = IM_COL32(60, 60, 60, 220);
for (int i = 0; i < num_segments; i++) {
float a0 = angle_start + (angle_end - angle_start) * ((float)i / num_segments);
float a1 = angle_start + (angle_end - angle_start) * ((float)(i + 1) / num_segments);
draw_list->AddLine(
ImVec2(center.x + cosf(a0) * radius, center.y + sinf(a0) * radius),
ImVec2(center.x + cosf(a1) * radius, center.y + sinf(a1) * radius),
bg_color, 6.0f);
}
// Normalize value to [0, 1]
float t = 0.0f;
if (max_val > min_val) {
t = (value - min_val) / (max_val - min_val);
if (t < 0.0f) t = 0.0f;
if (t > 1.0f) t = 1.0f;
}
// Color: green (t=0) -> yellow (t=0.5) -> red (t=1)
float r, g, b;
if (t < 0.5f) {
float s = t * 2.0f;
r = (unsigned char)(s * 255);
g = 200;
b = 0;
} else {
float s = (t - 0.5f) * 2.0f;
r = 220;
g = (unsigned char)((1.0f - s) * 200);
b = 0;
}
ImU32 value_color = IM_COL32((int)r, (int)g, (int)b, 255);
// Value arc
float angle_value = angle_start + (angle_end - angle_start) * t;
int value_segments = (int)(num_segments * t);
for (int i = 0; i < value_segments; i++) {
float a0 = angle_start + (angle_end - angle_start) * ((float)i / num_segments);
float a1 = angle_start + (angle_end - angle_start) * ((float)(i + 1) / num_segments);
draw_list->AddLine(
ImVec2(center.x + cosf(a0) * radius, center.y + sinf(a0) * radius),
ImVec2(center.x + cosf(a1) * radius, center.y + sinf(a1) * radius),
value_color, 6.0f);
}
// Needle: line from center to arc at current angle
float needle_len = radius * 0.75f;
ImVec2 needle_tip = ImVec2(
center.x + cosf(angle_value) * needle_len,
center.y + sinf(angle_value) * needle_len);
draw_list->AddLine(center, needle_tip, IM_COL32(255, 255, 255, 240), 2.0f);
draw_list->AddCircleFilled(center, 4.0f, IM_COL32(255, 255, 255, 200));
// Value text centered
char val_buf[32];
snprintf(val_buf, sizeof(val_buf), "%.1f", value);
ImVec2 val_size = ImGui::CalcTextSize(val_buf);
draw_list->AddText(
ImVec2(center.x - val_size.x * 0.5f, center.y + radius * 0.35f),
IM_COL32(230, 230, 230, 255), val_buf);
// Label below value
ImVec2 label_size = ImGui::CalcTextSize(label);
draw_list->AddText(
ImVec2(center.x - label_size.x * 0.5f, center.y + radius * 0.35f + val_size.y + 2.0f),
IM_COL32(180, 180, 180, 200), label);
}