5b73466bd4
Auditoria del issue 0044: anota en notes: el contexto de consumo de
huerfanos que no pueden registrarse en uses_functions porque sus
consumidores no son funciones del registry:
- consumido por cpp/framework/app_base.cpp (framework no indexado)
- consumido por cpp/apps/{shaders_lab,chart_demo,text_editor_smoke}/main.cpp
- scaffolding/demo en primitives_gallery
31 huerfanas anotadas. Las que quedan en uses_functions=[] tras esto
son hojas legitimas (no llaman a nada) o realmente sin uso (lista
DEAD reportada en el issue 0044).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.4 KiB
3.4 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, framework, params, output, notes
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | file_path | framework | params | output | notes | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| graph_force_layout | function | cpp | viz | 1.0.0 | pure | float graph_force_layout_step(GraphData& graph, const ForceLayoutConfig& config) | Layout force-directed con aproximacion Barnes-Hut para grafos grandes, ejecuta un paso de simulacion por llamada |
|
|
false | false | cpp/functions/viz/graph_force_layout.cpp | imgui |
|
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. | 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:
- 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. - 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. Contheta=0es O(n²) exacto; contheta=0.5es O(n log n). - Atraccion: para cada arista
(s, t), fuerza de HookeF = k * dist * weighten la direccion del arco. - Gravedad: fuerza proporcional a la distancia al origen, evita que el grafo derive fuera de pantalla.
- Integracion:
v = v * damping + F,pos += v, con clamping de velocidad. - Nodos con
pinned = trueno se mueven en ningun paso.
Funciones auxiliares
// 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)
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 reducirMAX_QUAD_NODESo aumentarlo segun memoria disponible. - La pila de traversal en
quad_forcees tambien estatica (static int stack[]); no es thread-safe si se llama desde multiples hilos simultaneamente. graph_force_layout_resetusarand(). Para reproducibilidad llamasrand(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.