b9ffc13caf
Extiende el modelo agnostico de graph_types.h para soportar shapes/iconos/ filtros/labels/streaming sin acoplar a backend. Migra el unico consumer (demos_graph) en el mismo cambio. - GraphNode v2: type_id + shape_override/color_override/size_override + flags (NF_PINNED/VISIBLE/SELECTED/HOVERED) + label_idx + user_data. - GraphEdge v2: type_id + style_override + flags (EF_DIRECTED/VISIBLE). - EntityType / RelationType: tablas en GraphData (types, rel_types). - Helpers de resolucion (resolve_node_color/shape/size, resolve_edge_*) y constructores ergonomicos (graph_node, graph_edge, entity_type, relation_type) — sentinel-based para herencia automatica del tipo. - graph_renderer v1.4: lee NF_VISIBLE / EF_VISIBLE, resuelve apariencia via override → EntityType → fallback indexado por type_id. Skipea aristas con endpoints invisibles. Shapes siguen pintandose como circulo (0049f cableara el dispatch real). - graph_force_layout v1.2: pinned ahora vive en flags & NF_PINNED. - graph_viewport v1.1: hover/seleccion publican NF_HOVERED/SELECTED en el grafo (clear-then-set). Drag usa NF_PINNED. Tooltip muestra Type/ user_data en lugar de community/value/label. - demos_graph: 8 EntityType (paleta antigua) + 1 RelationType. type_id por cluster. user_data = indice numerico del nodo. Apariencia visual identica al pre-cambio. - test_graph_types.cpp: 12 casos cubriendo helpers, defaults, bitmask manipulation y resoluciones override-vs-EntityType. test_graph_edge_ static actualizado al nuevo modelo (ya no tiene .color directo). - 4 .md de tipos nuevos (graph_node, graph_edge, entity_type, relation_type) + GraphData v2.0 actualizado. Tests: 31/31 ctest verdes (incluye test_visual golden). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.7 KiB
4.7 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.2.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 | true |
|
cpp/tests/test_graph_should_pause.cpp | 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);
// Auto-pause: parar la simulacion cuando la energia se ha estabilizado.
// Pure: el caller mantiene el contador, la funcion solo decide.
// bool graph_force_layout_should_pause(int low_frames, int min_consecutive);
Ejemplo de uso tipico (loop ImGui)
static ForceLayoutConfig cfg;
static bool running = true;
static int low_frames = 0;
const int k_min_consecutive = 30;
const float k_threshold_per_node = 0.001f;
if (running) {
float energy = graph_force_layout_step(my_graph, cfg);
float per_node = my_graph.node_count > 0
? energy / my_graph.node_count : 0.0f;
if (per_node < k_threshold_per_node) ++low_frames;
else low_frames = 0;
if (graph_force_layout_should_pause(low_frames, k_min_consecutive)) {
running = false;
low_frames = 0;
}
}
Notas de implementacion
- El quadtree usa un pool dinamico (
std::vector<QuadNode>) que se redimensiona una vez por step a5*N + 1024celdas. La pila de traversal enquad_forcees local en pila (256 entradas) — thread-safe bajo OpenMP. 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.
Notas de version
- v1.2 (2026-04-29, issue 0049e): el campo
pinneddesaparece del modelo deGraphNodey se sustituye porflags & NF_PINNED. La logica del integrador, atraccion, gravedad y reset usa el bit equivalente. Sin cambios en la API publica ni en el comportamiento. - v1.1 (2026-04-29, issue 0049c): añade el helper puro
graph_force_layout_should_pause(low_frames, min_consecutive)para que las apps detecten convergencia sin replicar el contador por todas partes. Sin cambios engraph_force_layout_stepni en la API existente. Test:cpp/tests/test_graph_should_pause.cpp.