Files
fn_registry/cpp/functions/viz/graph_labels_select.md
T
egutierrez bf94893032 feat(cpp/viz): split orphan TUs as separate fn entries (ADR 0003)
Cuando una funcion del registry parte su .cpp en varios TUs por testabilidad
o separacion ImGui-vs-puro, cada TU adicional se registra como entrada propia
con su .md en lugar de extender file_path para listar varios archivos.

Aplicado a:
- graph_labels_select_cpp_viz: helpers puros (compute_degrees + labels_select).
- graph_viewport_selection_cpp_viz: clear/add/toggle/is_selected puros.
- graph_types_cpp_viz: TU de update_bounds + find_node_by_user_data.

graph_labels y graph_viewport actualizados para declarar las nuevas entradas
en uses_functions. Razon detallada en docs/adr/0003 + regla actualizada en
.claude/rules/uses_functions.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 11:51:10 +02:00

4.6 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_labels_select function cpp viz 1.0.0 pure void graph::graph_compute_degrees(const GraphData& g, int* out_degrees); int graph::graph_labels_select(const GraphData& g, const LabelPolicy& p, float cam_x, float cam_y, float zoom, float widget_w, float widget_h, const int* degrees, int* out_indices, int out_capacity) Helpers puros (sin ImGui ni OpenGL) que calculan los nodos a etiquetar cada frame: graph_compute_degrees calcula el grado por nodo (solo aristas EF_VISIBLE), graph_labels_select aplica frustum cull + always_for_* + top-N por (size * (degree+1)) sobre min_node_pixel_size.
graph
labels
pure
culling
top-n
frustum
testable
GraphData_cpp_viz
false
true
select respects max_visible cap
min_node_pixel_size culling
always_for_selected gates by viewport
no callback / empty graph no-op
cpp/tests/test_graph_labels.cpp cpp/functions/viz/graph_labels_select.cpp imgui
name desc
g Grafo a procesar (lectura). Se respetan NF_VISIBLE, NF_SELECTED, NF_HOVERED, NF_PINNED, EF_VISIBLE.
name desc
out_degrees (compute_degrees) Array de tamaño node_count que recibe el grado por nodo. Cuenta solo aristas con EF_VISIBLE.
name desc
p LabelPolicy: max_visible (top-N), always_for_*, min_zoom_for_all, min_node_pixel_size.
name desc
cam_x Centro de la camara en world coords (X).
name desc
cam_y Centro de la camara en world coords (Y).
name desc
zoom Pixels por unidad world. zoom <= 0 → no-op.
name desc
widget_w Ancho del widget en pixeles.
name desc
widget_h Alto del widget en pixeles.
name desc
degrees Array de tamaño node_count con el grado por nodo. NULL → score = size sin factor degree.
name desc
out_indices Array de salida con los indices de nodos a etiquetar. Capacidad = out_capacity.
name desc
out_capacity Capacidad maxima de out_indices. La funcion no escribe mas alla.
graph_compute_degrees: void. graph_labels_select: numero de indices escritos en out_indices. Cap duro = max_visible + |always_*|. Issue 0049j. TU separado de graph_labels.cpp para que los tests unitarios puedan cubrir la seleccion de candidatos sin pintar nada (graph_labels.cpp depende de ImGui). Estrategia: (A) nodos always_* en viewport sin chequeo de pixel size; (B) resto de nodos visibles que cumplen min_node_pixel_size, capados al top-N por (size * (degree+1)). Off-screen always_* se OMITEN intencionadamente. El degree se puede precalcular (O(E)) y pasar al select para evitar recomputar.

graph_labels_select

Logica pura de seleccion de etiquetas para graph_labels. Vive en su propio TU (graph_labels_select.cpp) — separada de graph_labels.cpp (que tiene la parte de pintado con ImGui) — para que los tests unitarios puedan ejercerla sin abrir una ventana.

API

namespace graph {
    // Grado por nodo (cuenta solo aristas EF_VISIBLE). O(E).
    void graph_compute_degrees(const GraphData& g, int* out_degrees);

    // Devuelve los indices de los nodos a etiquetar este frame.
    // O(N) frustum cull + O(K log K) si K candidatos > max_visible.
    int graph_labels_select(const GraphData& g, const LabelPolicy& p,
                            float cam_x, float cam_y, float zoom,
                            float widget_w, float widget_h,
                            const int* degrees,
                            int* out_indices, int out_capacity);
}

Composabilidad

  • Lo usa graph_labels_draw y graph_labels_draw_at internamente cada frame.
  • Una app puede llamarlo directamente para pintar etiquetas con su propio renderer (no-ImGui) reusando la misma politica.
  • Sin dependencias de ImGui ni OpenGL — puro <algorithm> + <vector>.

Estrategia (resumen)

  1. Pase A — always_*: nodos selected/hovered/pinned visibles en viewport. Skip de min_node_pixel_size. Off-screen NO entra (decision documentada).
  2. Pase B — top-N: del resto de nodos visibles en viewport con size * zoom >= min_node_pixel_size, ordena por score = size * (degree+1) y coge los max_visible primeros (std::partial_sort).
  3. Cap duro: max_visible + |always_*|. Imposible saltarse — si quieres 0 labels excepto always, pon max_visible = 0.

Tests

Cubiertos en cpp/tests/test_graph_labels.cpp. La funcion devuelve int sin tocar ImGui — pasable a assert(graph_labels_select(...) == N).