chore(issues): close 0034 — C++ scientific viz
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# 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
|
||||
|
||||
```cpp
|
||||
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`.
|
||||
|
||||
### Fase 6 — Gallery demos
|
||||
|
||||
- 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
|
||||
|
||||
```cpp
|
||||
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.
|
||||
Reference in New Issue
Block a user