7644a50d00
Phase 1 — graph_layouts:
- New module cpp/functions/viz/graph_layouts.{h,cpp,md} v1.0.0
- layout_grid, layout_circular, layout_random (migrated from graph_force_layout.cpp)
- layout_radial: BFS rings from root, hop k -> circle of radius k*ring_spacing
- layout_hierarchical: Sugiyama-style heuristic (longest-path levels + barycenter ordering)
- layout_fixed: no-op
- All respect NF_PINNED. graph_layout_circular/grid kept as deprecated wrappers.
Phase 2-3 — graph_viewport v1.2.0:
- Multi-selection via state.selection (vector<int>); NF_SELECTED kept in sync
- Lasso: Shift+Drag on empty area; AABB hit-test on release
- Drag of N-selection: all selected pinned + moved by mouse delta
- Ctrl+click toggle, Esc clears selection
- Right-click on node -> on_context_menu callback
- Double-click on node -> on_double_click callback
- Helpers exposed: graph_viewport_clear/add_to/toggle/is_selected (own TU for tests)
Phase 4 — tests:
- test_graph_layouts: 12 cases / 364 assertions covering geometry, pin, edges
- test_graph_viewport: 5 cases for selection helpers (pure logic, no GL)
Phase 5 — demo (primitives_gallery):
- Layout combo (force/grid/circular/radial/hierarchical/fixed) + Apply button
- Right-click popup with Pin/Unpin/Add-to-selection
- Status overlay shows [N selected] when selection non-empty
- Updated golden images
Issue moved to dev/issues/completed/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
52 lines
2.1 KiB
C++
52 lines
2.1 KiB
C++
#pragma once
|
|
|
|
// Layouts estaticos (no iterativos) para GraphData. Todos respetan NF_PINNED:
|
|
// los nodos con ese flag conservan su posicion y velocidad. Las velocidades
|
|
// del resto se ponen a cero al aplicar un layout.
|
|
//
|
|
// Para layouts iterativos (force-directed) ver graph_force_layout.h /
|
|
// graph_force_layout_gpu.h.
|
|
|
|
struct GraphData;
|
|
|
|
namespace graph {
|
|
|
|
// Cuadricula uniforme. spacing en world units. Coloca los nodos en columnas
|
|
// de ceil(sqrt(N)) hasta filas. Centro del grafo en (0,0).
|
|
void layout_grid (GraphData& graph, float spacing = 20.0f);
|
|
|
|
// Circulo unico de radio `radius`. Centro en (0,0).
|
|
void layout_circular (GraphData& graph, float radius = 100.0f);
|
|
|
|
// Posiciones aleatorias en [-spread, spread] x [-spread, spread]. Usa rand();
|
|
// el caller puede llamar srand(seed) antes para reproducibilidad.
|
|
void layout_random (GraphData& graph, float spread = 200.0f);
|
|
|
|
// Layout radial tipo arbol: BFS desde `root_node`. Hop k -> circulo de radio
|
|
// k * ring_spacing. Nodos del mismo hop se distribuyen uniformemente en su
|
|
// circulo. Nodos no alcanzables (componentes desconectadas) van al ultimo hop+1.
|
|
// Si `root_node` es invalido, usa el indice 0.
|
|
void layout_radial (GraphData& graph, int root_node = 0,
|
|
float ring_spacing = 80.0f);
|
|
|
|
// Layout jerarquico estilo Sugiyama (heuristico). Asigna niveles via BFS
|
|
// desde nodos sin in-edges (rank por longest-path). Dentro de cada nivel
|
|
// ordena por baricentro respecto al nivel previo (greedy) para reducir
|
|
// cruces de aristas.
|
|
//
|
|
// direction:
|
|
// 0 = LR (left -> right, niveles en X creciente)
|
|
// 1 = RL (right -> left)
|
|
// 2 = TB (top -> bottom, niveles en Y creciente)
|
|
// 3 = BT (bottom -> top)
|
|
void layout_hierarchical(GraphData& graph, int direction = 0,
|
|
float layer_spacing = 120.0f,
|
|
float node_spacing = 60.0f);
|
|
|
|
// No-op. Existe para que los callers puedan tratar "fixed" como un layout
|
|
// mas en un switch sin casos especiales. NO toca posiciones, velocidades ni
|
|
// flags.
|
|
void layout_fixed (GraphData& graph);
|
|
|
|
} // namespace graph
|