---
name: graph_force_layout
kind: function
lang: cpp
domain: viz
version: "1.0.0"
purity: pure
signature: "float graph_force_layout_step(GraphData& graph, const ForceLayoutConfig& config)"
description: "Layout force-directed con aproximacion Barnes-Hut para grafos grandes, ejecuta un paso de simulacion por llamada"
tags: [graph, layout, force-directed, barnes-hut, physics, gpu]
uses_functions: []
uses_types: ["GraphData_cpp_viz"]
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "cpp/functions/viz/graph_force_layout.cpp"
framework: imgui
params:
  - name: graph
    desc: "Referencia al grafo (GraphData) cuyos nodos se actualizan in-place. Modifica x, y, vx, vy de cada nodo no pinned."
  - name: config
    desc: "Parametros de la simulacion: repulsion (fuerza coulombiana), attraction (spring constant), damping (decay de velocidad), theta (precision Barnes-Hut 0=exacto/1=rapido), gravity (atraccion al centro), max_velocity, iterations."
output: "Energia cinetica total (suma de |v|^2). Cuando cae por debajo de un umbral elegido por el caller, el layout ha convergido y se puede dejar de llamar."
notes: "scaffolding/demo en primitives_gallery"
---

# graph_force_layout

Implementa el algoritmo de layout force-directed clasico (Fruchterman-Reingold / Eades) con aproximacion Barnes-Hut O(n log n) para escalar a grafos de miles de nodos.

## Algoritmo

Cada llamada a `graph_force_layout_step` ejecuta `config.iterations` pasos. Un paso:

1. **Construccion del quadtree** (Barnes-Hut): se calcula el bounding box de las posiciones actuales, se construye un quadtree flat en `quad_pool` (sin allocaciones por nodo). Cada celda acumula centro de masa y masa total.
2. **Repulsion**: para cada nodo se recorre el quadtree. Si el cociente `cell_size / distance < theta`, la celda se trata como una sola masa puntual (multipolo de orden 0). Si no, se desciende a los hijos. Con `theta=0` es O(n²) exacto; con `theta=0.5` es O(n log n).
3. **Atraccion**: para cada arista `(s, t)`, fuerza de Hooke `F = k * dist * weight` en la direccion del arco.
4. **Gravedad**: fuerza proporcional a la distancia al origen, evita que el grafo derive fuera de pantalla.
5. **Integracion**: `v = v * damping + F`, `pos += v`, con clamping de velocidad.
6. Nodos con `pinned = true` no se mueven en ningun paso.

## Funciones auxiliares

```cpp
// Randomizar posiciones para empezar la simulacion
graph_force_layout_reset(graph, 200.0f);

// Layout circular instantaneo (sin iteracion)
graph_layout_circular(graph, 150.0f);

// Layout en grid instantaneo
graph_layout_grid(graph, 25.0f);
```

## Ejemplo de uso tipico (loop ImGui)

```cpp
static ForceLayoutConfig cfg;
static bool running = true;

if (running) {
    float energy = graph_force_layout_step(my_graph, cfg);
    if (energy < 0.01f) running = false; // convergido
}
```

## Notas de implementacion

- El quadtree usa un pool estatico de `1 << 20` (~1M) celdas. Para grafos de >500K nodos
  se recomienda reducir `MAX_QUAD_NODES` o aumentarlo segun memoria disponible.
- La pila de traversal en `quad_force` es tambien estatica (`static int stack[]`); no es
  thread-safe si se llama desde multiples hilos simultaneamente.
- `graph_force_layout_reset` usa `rand()`. Para reproducibilidad llama `srand(seed)` antes.
- Los buffers de fuerza (`fx_buf`, `fy_buf`) se realocan una sola vez cuando el conteo de
  nodos supera la capacidad previa; en el uso normal (tamano fijo) no hay allocaciones
  por frame.
