Files
fn_registry/dev/issues/completed/0034-cpp-scientific-viz.md
T

6.2 KiB
Raw Blame History

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0034 C++ scientific viz (treemap, sankey, chord, contour, voronoi) completado feature
cpp-stack
multi-app media
2026-05-17 2026-05-17

0034 — C++ scientific viz (treemap, sankey, chord, contour, voronoi)

APP Metadata

Campo Valor
ID 0034
Estado pendiente
Prioridad media
Tipo feature — C++ viz (cpp/functions/viz)

Dependencias

tokens_cpp_core, plot_theme_cpp_core. ImPlot ya vendoreado. Sin bloqueos por otros issues.

Desbloquea: dashboards con tipos de visualizacion mas alla de bar/line/scatter — utiles para jerarquias, flujos, relaciones, distribuciones 2D continuas.


Objetivo

Cinco componentes nuevos en cpp/functions/viz/, cada uno con su demo en gallery:

  1. treemap_cpp_viz — squarified treemap (Bruls, Huijbrechts, van Wijk) para jerarquias planas con valores. Click hace zoom (opcional MVP: solo render).
  2. sankey_cpp_viz — sankey diagram para flujos source → target con magnitudes.
  3. chord_cpp_viz — chord diagram para matrices de relaciones N×N (ej: flujos entre N entidades).
  4. contour_cpp_viz — contour plot de un grid 2D escalar (marching squares con N niveles).
  5. voronoi_cpp_viz — diagrama de Voronoi (Fortune o aproximacion via ImGui draw): regiones coloreadas a partir de N seeds.

Todos los layouts/algoritmos deben ser puros; el render usa primitivas ImGui DrawList (AddTriangleFilled, AddBezierQuadratic, etc.).

Contexto

cpp/functions/viz/ cubre charts standard (bar/line/scatter/heatmap/histogram/pie/candlestick/sparkline + table + graph). Faltan las visualizaciones "narrativas" tipicas de dashboards mas avanzados.

Implementar 5 a la vez es viable porque comparten la misma estructura: compute_layout puro + render con DrawList.

Arquitectura

cpp/functions/viz/
├── treemap.h/.cpp/.md           # NEW
├── sankey.h/.cpp/.md            # NEW
├── chord.h/.cpp/.md             # NEW
├── contour.h/.cpp/.md           # NEW
└── voronoi.h/.cpp/.md           # NEW
cpp/apps/primitives_gallery/
├── demos_scientific.cpp         # NEW (5 demos en un archivo)
├── demos.h                      # MOD
├── main.cpp                     # MOD
└── CMakeLists.txt               # MOD

API propuesta

namespace fn {

// --- treemap ---
struct TreemapItem { std::string label; float value; ImU32 color; };
struct TreemapRect { ImVec2 min, max; const TreemapItem* item; };
std::vector<TreemapRect> treemap_layout(const std::vector<TreemapItem>&, ImVec2 region);  // pure
void treemap(const char* id, const std::vector<TreemapItem>&, ImVec2 size = {-1, 300});

// --- sankey ---
struct SankeyNode { std::string label; };
struct SankeyLink { int src, dst; float value; };
void sankey(const char* id,
            const std::vector<SankeyNode>&, const std::vector<SankeyLink>&,
            ImVec2 size = {-1, 400});

// --- chord ---
void chord(const char* id,
           const float* matrix, int n, const char* const* labels,
           ImVec2 size = {400, 400});

// --- contour ---
struct ContourLine { std::vector<ImVec2> pts; float level; };
std::vector<ContourLine> contour_compute(const float* grid, int nx, int ny, const float* levels, int n_levels);  // pure (marching squares)
void contour(const char* id, const float* grid, int nx, int ny, const float* levels, int n_levels,
             ImVec2 size = {-1, 300});

// --- voronoi ---
struct VoronoiCell { std::vector<ImVec2> polygon; ImVec2 seed; ImU32 color; };
std::vector<VoronoiCell> voronoi_layout(const ImVec2* seeds, int n, ImVec2 region);  // pure
void voronoi(const char* id, const ImVec2* seeds, int n, const ImU32* colors, ImVec2 size = {-1, 300});
}

Tareas

Fase 1 — treemap

  • 1.1 Implementar squarified algorithm (recursivo, O(n log n)).
  • 1.2 Render con AddRectFilled + AddText (label si cabe).
  • 1.3 Tests con 5 items conocidos.
  • 1.4 .md.

Fase 2 — sankey

  • 2.1 Asignar nodos a columnas via topological levels (BFS desde sources).
  • 2.2 Stack vertical de cada columna por valor; calcular Y offset por link.
  • 2.3 Render: rectangulos para nodos + bezier cubic para links.
  • 2.4 .md.

Fase 3 — chord

  • 3.1 Calcular angulos por nodo proporcionales a sum(matrix[i,*]).
  • 3.2 Arcos en el borde del circulo + bezier interno entre arcos.
  • 3.3 .md.

Fase 4 — contour

  • 4.1 contour_compute con marching squares clasico (16 casos), interp lineal entre celdas.
  • 4.2 Render: AddPolyline por cada level, color por level (gradiente).
  • 4.3 Tests con grid conocido (gaussiana → contornos circulares).
  • 4.4 .md.

Fase 5 — voronoi

  • 5.1 MVP: implementacion brute-force (para cada pixel, encontrar seed mas cercana). Para N pequeño (<200) y region <500², es < 1ms.
  • 5.2 Para layout poligonal: usar half-plane intersections (mas complejo). MVP puede renderizar como raster a una textura cacheada.
  • 5.3 .md.
  • 6.1 demos_scientific.cpp con 5 funciones, una por chart, datos sinteticos coherentes (treemap: gastos por categoria; sankey: flujos cliente→producto; chord: relaciones entre paises; contour: gaussiana mezcla; voronoi: 30 seeds aleatorios).
  • 6.2 Registrar en gallery.

Fase 7 — Tests + docs

  • 7.1 Tests por componente (algorithm puro, no render).
  • 7.2 ./fn index + ./fn show para los 5.

Ejemplo de uso

std::vector<fn::TreemapItem> items = {
    {"comida", 320, IM_COL32(120,180,200,255)},
    {"vivienda", 950, IM_COL32(180,120,200,255)},
    {"transporte", 180, IM_COL32(200,180,120,255)},
};
fn::treemap("##gastos", items);

Decisiones de diseño

  • Render con DrawList (no ImPlot) para chart types que ImPlot no soporta nativo.
  • Layout puro separado del render: facilita tests y reuso (treemap → exportar a SVG futuro).
  • Voronoi raster en MVP: simple, suficiente. Si hace falta poligonos, otro issue.

Riesgos

  • Tamaño del issue: 5 charts es mucho. Mitigacion: comparten patron y un archivo demos_scientific.cpp. Si un agente no termina, sub-issue por chart.
  • Voronoi performance: documentar limite practico N <= 200.
  • Sankey con grafo ciclico: assumir DAG; documentar.