7eef2544ab
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>
95 lines
3.5 KiB
C++
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);
|
|
}
|