05_02_01_visualization_engine - Motor de Renderización Visual¶
🎨 Propósito¶
El Visualization Engine transforma la estructura abstracta del grafo en representaciones visuales comprensibles usando algoritmos de layout que minimizan cruces y maximizan legibilidad. Soporta múltiples formatos de salida para diferentes contextos de uso.
🏗️ Arquitectura¶
Componentes Principales¶
05_02_01_visualization_engine/
├── layout_engine.hpp # Algoritmos de layout
├── renderers.hpp # Backends de renderización
├── d3_template.html # Template interactivo web
└── README.md # Documentación
🔄 Pipeline de Visualización¶
Graph Structure
↓
Layout Algorithm (position nodes/edges)
↓
Rendering Backend (generate output format)
↓
Visual Output (DOT, JSON, ASCII, Mermaid, HTML)
📐 Algoritmos de Layout¶
1. Hierarchical Layout (Sugiyama's Framework)¶
Mejor para: Grafos de dependencias DSP con jerarquía clara
Algoritmo: 1. Layer Assignment: Agrupar nodos por nivel jerárquico (L0→L1→L2→L3) 2. Crossing Minimization: Ordenar nodos dentro de capas usando heurística barycenter 3. Coordinate Assignment: Posicionar nodos minimizando longitud de aristas
Uso:
#include "layout_engine.hpp"
using namespace audio_lab::dependency_graph::visualization;
Graph graph = /* ... */;
LayoutConfig config;
config.width = 1200.0;
config.height = 800.0;
config.level_spacing = 150.0;
HierarchicalLayout layout(graph, config);
LayoutMap positions = layout.compute();
Output:
2. Force-Directed Layout (Fruchterman-Reingold)¶
Mejor para: Exploración libre, detección de clusters
Algoritmo: - Nodos se repelen entre sí (como partículas cargadas) - Aristas atraen nodos conectados (como resortes) - Sistema converge a equilibrio visualmente balanceado
Parámetros:
- node_spacing: Distancia óptima entre nodos (k)
- max_iterations: Iteraciones de simulación (típico: 50-100)
- temperature: Temperatura inicial (controla movimiento)
- cooling_factor: Decay por iteración (típico: 0.95)
Uso:
3. Circular Layout¶
Mejor para: Visualizar simetría, detectar patrones circulares
Algoritmo: - Distribuir nodos equidistantes en círculo - Radio = 40% de min(width, height)
Uso:
4. Tree Layout (Reingold-Tilford)¶
Mejor para: Subgrafos arbóreos, jerarquías estrictas
Algoritmo: - Encontrar nodos raíz (sin dependencias) - Calcular profundidad por BFS - Posicionar nivel por nivel
Uso:
Factory Pattern¶
// Uso simplificado con factory
LayoutMap positions = LayoutFactory::compute_layout(
graph,
LayoutAlgorithm::HIERARCHICAL,
config
);
🎨 Backends de Renderización¶
1. GraphViz DOT¶
Para: Imágenes estáticas de alta calidad (PDF, PNG, SVG)
Características: - Sintaxis DOT estándar - Subgraphs por nivel jerárquico - Colorización automática - Tooltips con métricas - Estilos por estado (stable=sólido, beta=punteado, etc.)
Uso:
#include "renderers.hpp"
DotRenderer renderer(graph);
std::string dot_output = renderer
.with_positions(positions)
.render();
// Guardar y generar imagen
std::ofstream file("graph.dot");
file << dot_output;
file.close();
// Comando externo:
// dot -Tsvg graph.dot -o graph.svg
Output:
digraph DependencyGraph {
rankdir=BT;
node [shape=box, style=rounded];
"add_kernel" [label="Add Kernel\nL0_KERNEL",
color="#0066CC",
style="solid,filled"];
"svf_filter" [label="SVF Filter\nL1_ATOM",
color="#00AA44",
style="solid,filled"];
"svf_filter" -> "add_kernel";
}
2. D3.js JSON¶
Para: Visualización web interactiva
Características: - JSON compatible con D3.js - Posiciones pre-calculadas o dinámicas - Metadata de nodos/aristas - Estadísticas del grafo
Uso:
D3JsonRenderer renderer(graph);
std::string json_output = renderer
.with_positions(positions)
.render();
// Guardar JSON
std::ofstream file("graph.json");
file << json_output;
Output:
{
"nodes": [
{
"id": "add_kernel",
"label": "Add Kernel",
"level": "L0_KERNEL",
"color": "#0066CC",
"cpu_cycles": 10,
"x": 500,
"y": 100
}
],
"links": [
{
"source": 1,
"target": 0,
"type": "REQUIRED"
}
]
}
Integración Web:
1. Generar JSON
2. Reemplazar {{GRAPH_DATA}} en d3_template.html
3. Abrir en navegador → Visualización interactiva
3. ASCII Art¶
Para: Terminal/CLI, visualización rápida
Características: - Árbol jerárquico con box-drawing characters - Información compacta (nivel + CPU) - Detección de ciclos
Uso:
Output:
└── [L0_KERNEL] Add Kernel (CPU: 10)
└── [L1_ATOM] SVF Filter (CPU: 120)
└── [L2_CELL] Synth Voice (CPU: 450)
└── [L3_ENGINE] Poly Synth (CPU: 2000)
4. Mermaid¶
Para: Documentación Markdown (GitHub, GitLab)
Características: - Sintaxis Mermaid embebible - Renderiza automáticamente en GitHub - Estilos por nivel (classDef) - Flechas según tipo de dependencia
Uso:
Output:
```mermaid
graph TD
add_kernel["Add Kernel<br/>L0_KERNEL"]:::l0_style
svf_filter["SVF Filter<br/>L1_ATOM"]:::l1_style
svf_filter --> add_kernel
classDef l0_style fill:#0066CC,stroke:#004499,color:#fff
classDef l1_style fill:#00AA44,stroke:#007722,color:#fff
```
Factory Pattern¶
🌈 Sistema de Estilos¶
Colorización por Nivel Jerárquico¶
| Nivel | Color | Hex | Significado |
|---|---|---|---|
| L0_KERNEL | 🔵 Azul | #0066CC |
Fundacional (océano profundo) |
| L1_ATOM | 🟢 Verde | #00AA44 |
Crecimiento (bloques vivos) |
| L2_CELL | 🟡 Amarillo | #FFAA00 |
Complejidad media (advertencia) |
| L3_ENGINE | 🔴 Rojo | #CC0000 |
Máxima complejidad (calor) |
Estilos por Estado¶
| Estado | Estilo | GraphViz | Mermaid |
|---|---|---|---|
| STABLE | Sólido | solid |
--> |
| BETA | Punteado | dashed |
-.-> |
| EXPERIMENTAL | Puntos | dotted |
-.-> |
| DEPRECATED | Gris + tachado | bold,dashed |
~~> |
Visualización de Métricas¶
- CPU usage → Grosor de borde proporcional
- Many dependencies → Tamaño de nodo más grande
- Critical path → Aristas más gruesas
- High betweenness → Nodo destacado
🖥️ Visualización Web Interactiva¶
Características del Template D3¶
Controles: - ✅ Selector de layout (Force/Hierarchical/Circular) - ✅ Filtrado por nivel jerárquico - ✅ Filtrado por categoría - ✅ Toggle labels/edges - ✅ Zoom & Pan - ✅ Drag nodes - ✅ Tooltips informativos
Estadísticas en Tiempo Real: - Número de nodos - Número de aristas - Densidad del grafo - Grado promedio
Uso:
# 1. Generar JSON
./visualizer export --format d3-json > graph.json
# 2. Sustituir en template
sed 's/{{GRAPH_DATA}}/'"$(cat graph.json)"'/' d3_template.html > viz.html
# 3. Abrir en navegador
open viz.html
🧪 Testing¶
Casos de Prueba¶
TEST_CASE("Hierarchical layout positions nodes correctly") {
auto graph = create_simple_graph();
LayoutConfig config;
config.width = 1000;
config.height = 800;
HierarchicalLayout layout(graph, config);
auto positions = layout.compute();
// Verificar que L0 está más abajo que L3
REQUIRE(positions["add_kernel"].y > positions["poly_synth"].y);
}
TEST_CASE("DOT renderer generates valid syntax") {
auto graph = create_simple_graph();
DotRenderer renderer(graph);
std::string dot = renderer.render();
REQUIRE(dot.find("digraph") != std::string::npos);
REQUIRE(dot.find("add_kernel") != std::string::npos);
}
Benchmarks¶
| Operación | Target | Resultado |
|---|---|---|
| Hierarchical layout (100 nodes) | <50ms | ✅ |
| Force-directed (100 nodes, 100 iter) | <500ms | ✅ |
| DOT render (500 nodes) | <100ms | ✅ |
| D3 JSON render (500 nodes) | <50ms | ✅ |
📊 Complejidad¶
| Algoritmo | Tiempo | Espacio |
|---|---|---|
| Hierarchical | O(E + V log V) | O(V) |
| Force-Directed | O(I × V²) donde I=iterations | O(V) |
| Circular | O(V) | O(V) |
| Tree | O(V + E) | O(V) |
| DOT render | O(V + E) | O(V + E) |
| JSON render | O(V + E) | O(V + E) |
🔗 Dependencias¶
# Bibliotecas C++
vcpkg install nlohmann-json:x64-windows
# Herramientas externas (opcional)
# GraphViz para generar imágenes
choco install graphviz
# o
brew install graphviz
📝 Ejemplos Completos¶
Ejemplo 1: Pipeline Completo¶
#include "layout_engine.hpp"
#include "renderers.hpp"
// 1. Construir grafo
Graph graph;
GraphBuilder builder(graph);
builder.build_from_catalog("catalog.json");
// 2. Calcular layout
LayoutConfig config;
config.width = 1200;
config.height = 900;
auto positions = LayoutFactory::compute_layout(
graph,
LayoutAlgorithm::HIERARCHICAL,
config
);
// 3. Renderizar en múltiples formatos
auto dot = RenderFactory::render(graph, RenderFormat::DOT, &positions);
auto json = RenderFactory::render(graph, RenderFormat::D3_JSON, &positions);
auto ascii = RenderFactory::render(graph, RenderFormat::ASCII);
auto mermaid = RenderFactory::render(graph, RenderFormat::MERMAID);
// 4. Guardar outputs
save_file("graph.dot", dot);
save_file("graph.json", json);
std::cout << ascii << std::endl;
save_file("ARCHITECTURE.md", "# Architecture\n\n" + mermaid);
Ejemplo 2: Generación de SVG¶
// Generar DOT
DotRenderer renderer(graph);
std::string dot = renderer.render();
// Guardar
std::ofstream file("output.dot");
file << dot;
file.close();
// Ejecutar GraphViz (requiere graphviz instalado)
system("dot -Tsvg output.dot -o output.svg");
system("dot -Tpng output.dot -o output.png -Gdpi=300");
Ejemplo 3: Visualización Web Standalone¶
// Generar JSON
D3JsonRenderer renderer(graph);
auto json = renderer.render();
// Leer template
std::ifstream template_file("d3_template.html");
std::string html_template((std::istreambuf_iterator<char>(template_file)),
std::istreambuf_iterator<char>());
// Sustituir placeholder
size_t pos = html_template.find("{{GRAPH_DATA}}");
html_template.replace(pos, 14, json);
// Guardar HTML standalone
std::ofstream output("visualization.html");
output << html_template;
output.close();
std::cout << "Open visualization.html in browser" << std::endl;
🚀 Próximos Pasos¶
✅ Completado: - Layout algorithms (4 tipos) - Rendering backends (4 formatos) - Sistema de estilos completo - Template web interactivo
⏳ Pendiente: - Exportación de imágenes desde C++ (sin GraphViz CLI) - Optimización de force-directed para >1000 nodos - Layout híbrido (hierarchical + force dentro de niveles) - Clustering automático para grafos grandes - Progressive rendering para grafos masivos
Status: ✅ Visualización Core Completa Formatos soportados: 4 (DOT, D3-JSON, ASCII, Mermaid) Layouts implementados: 4 (Hierarchical, Force-Directed, Circular, Tree)