Rerun GraphNodes 图节点 Archetype 完整指南:字段、坐标布局与 Python/Rust/C++ 实战
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
GraphNodes是 Rerun 中用于可视化图(Graph)数据的基础 archetype,它描述了一组带可选标签、颜色、位置与半径的图节点。本文以 docs/content/reference/types/archetypes/graph_nodes.md 为主体,结合仓库中三种语言(Python / Rust / C++)的生成实现与官方示例,讲解GraphNodes的每个字段、与GraphEdges的配合方式、可用的展示视图,以及它背后的类型定义与代码生成机制,帮助你在自己的多模态数据可视化流程中直接落地图结构数据。
GraphNodes 在 Rerun 数据模型中的定位
Rerun 采用“Archetype(原型)— Component(组件)— Batch(批次)”的分层数据模型:archetype 是面向用户的高层数据结构,由若干组件组成;组件描述单个属性,批处理则对应 Arrow 数组列。GraphNodes正是这样一类 archetype,用于"承载一张图中所有节点的描述"。
它的类型定义源头位于 crates/build/re_type_definitions/rerun/archetypes/graph_nodes.def.rs,这是一份由re_types_builder解析的 Rerun 类型定义(非可执行代码)。该定义文件同时标注了:
#[docs(category = "Graph")]:归属于 Graph 类别;#[docs(view_types = "GraphView")]:主要面向GraphView展示;#[rerun(state = "stable")]:API 状态为稳定;#[rerun(visualizer = "GraphNodes")]:绑定同名 visualizer。
而面向最终用户的参考文档 graph_nodes.md 是由crates/build/re_types_builder/src/codegen/docs/website.rs自动生成的,因此文档中的字段列表与三种语言 SDK 的 API 始终保持一致——这保证了本文所述的字段结构即当前仓库各 SDK 的实际 API。
字段与组件类型对照
GraphNodes共包含 6 个字段:1 个必填字段 + 5 个可选字段。字段与底层组件的对应关系如下(依据 graph_nodes.md 与三种语言实现):
| 字段 | 对应组件 | 必填/可选 | 说明 |
|---|---|---|---|
node_ids | GraphNode | 必填 | 节点 ID 列表,是节点唯一标识 |
positions | Position2D | 可选 | 节点的中心位置(二维坐标) |
colors | Color | 可选 | 节点的颜色 |
labels | Text | 可选 | 节点的文本标签 |
show_labels | ShowLabels | 可选 | 是否显示文本标签 |
radii | Radius | 可选 | 节点的半径(大小) |
从 Rust 生成实现 crates/store/re_sdk_types/src/archetypes/graph_nodes.rs 可以看到,编译器将组件分成三组注册:REQUIRED_COMPONENTS(仅node_ids)、RECOMMENDED_COMPONENTS(为空)、OPTIONAL_COMPONENTS(positions、colors、labels、show_labels、radii共 5 个),总数NUM_COMPONENTS = 6。这说明除node_ids外,其余字段均可按需填充,未设置的字段不会写入数据流。
各字段详解
node_ids(必填):节点的身份
node_ids是GraphNodes唯一必填字段,类型为GraphNode组件列表。它是每个节点的唯一标识,也是后续GraphEdges引用节点的"主键"。在 graph_nodes.def.rs 中该字段被标记为#[rerun(required)],同时带有#[rerun(no_ui_edit)](不参与 UI 编辑)。示例中节点 ID 通常为字符串(如"a"、"b"、"c"),但本质上它可以是任意可序列化的GraphNode值。
positions(可选):节点的坐标布局
positions是Position2D组件列表,表示节点的中心位置,直接决定节点在 2D 空间中的摆放。定义注释将其描述为 "Optional center positions of the nodes"。
设置positions后,图将按你给定的坐标静态布局;不设置时,GraphView会启用内置的力导向布局(force-directed layout)自动排布节点,这对节点数量较多、没有明确空间语义的拓扑图尤其有用。
colors(可选):节点颜色
colors是Color组件列表,用于为节点着色。定义注释中的表述为 "Optional colors for the boxes",即作用于节点的填充色。每个节点可指定一个 RGBA 颜色值,也可只提供 RGB。
labels(可选)与 show_labels(可选):文本标签控制
labels是Text组件列表,为每个节点附加一个文本标签;show_labels是ShowLabels组件(单个布尔值),控制标签是否显示。两者在源码注释中有一处重要的自动行为说明(见 graph_nodes.def.rs 与 graph_nodes.rs):
If not set, labels will automatically appear when there is exactly one label for this entity or the number of instances on this entity is under a certain threshold. (若未显式设置,当该实体只有一个标签、或实体上的实例数量低于某个阈值时,标签会自动出现。)
也就是说,show_labels缺省时由 Rerun 根据数据规模自动决定是否展示标签,避免在大规模图(海量节点)时标签互相遮挡;当你需要强制显示或隐藏时,再显式传入该字段。
radii(可选):节点半径
radii是Radius组件列表,用于控制每个节点的绘制半径(大小)。它可以配合GraphView的碰撞力(collision force)使用——在 graph_view.md 中,force_collision_radius属性描述为"根据节点的半径解析节点包围球之间的碰撞",因此合理的半径设置会让布局更自然地避让重叠。
三种语言快速上手
仓库在 docs/snippets/all/archetypes/ 中提供了graph_undirected(无向图)与graph_directed(有向图)两个官方示例,分别有 Python、Rust、C++ 三个版本,并预生成了对应的.rrd录制文件(位于 tests/assets/rrd/snippets/archetypes/),可以直接用 Rerun Viewer 打开查看渲染结果。
无向图(默认类型)
Python(graph_undirected.py):
"""Log a simple undirected graph.""" import rerun as rr rr.init("rerun_example_graph_undirected", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"], ), rr.GraphEdges( edges=[("a", "b"), ("b", "c"), ("c", "a")], # Optional: graphs are undirected by default. graph_type="undirected", ), )Rust(graph_undirected.rs):
//! Log a simple undirected graph. fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_graph_undirected") .spawn()?; rec.log( "simple", &[ &rerun::GraphNodes::new(["a", "b", "c"]) .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) .with_labels(["A", "B", "C"]) as &dyn rerun::AsComponents, &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]) // Optional: graphs are undirected by default. .with_undirected_edges(), ], )?; Ok(()) }C++(graph_undirected.cpp):
//! Log a simple undirected graph. #include <rerun.hpp> int main(int argc, char* argv[]) { const auto rec = rerun::RecordingStream("rerun_example_graph_undirected"); rec.spawn().exit_on_failure(); rec.log( "simple", rerun::GraphNodes({"a", "b", "c"}) .with_positions({{0.0, 100.0}, {-100.0, 0.0}, {100.0, 0.0}}) .with_labels({"A", "B", "C"}), rerun::GraphEdges({{"a", "b"}, {"b", "c"}, {"c", "a"}}) // Optional: graphs are undirected by default. .with_graph_type(rerun::GraphType::Undirected) ); }三个示例把 3 个节点放在一个等边三角形的位置上((0, 100)、(-100, 0)、(100, 0)),并给出标签A/B/C,再用 3 条边a-b、b-c、c-a连成一个环。注意:无向图是默认行为,graph_type="undirected"一行是可选的。
有向图
有向图与无向图的唯一区别在于边方向的显式声明。Python(graph_directed.py):
"""Log a simple directed graph.""" import rerun as rr rr.init("rerun_example_graph_directed", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"], ), rr.GraphEdges( edges=[("a", "b"), ("b", "c"), ("c", "a")], graph_type="directed" ), )Rust(graph_directed.rs)与 C++ 版本(见 rerun_cpp 中的 GraphNodes 头文件 内嵌示例)结构一致,Rust 使用.with_directed_edges(),C++ 使用.with_graph_type(rerun::GraphType::Directed)。
从上述示例可以看出三个要点:
GraphNodes与GraphEdges是成对使用的:节点只负责"有哪些点",边的连接关系完全由GraphEdges决定;- 节点 ID(
node_ids)是GraphNodes与GraphEdges之间建立关联的键——边的两个端点必须引用已存在的节点 ID; - 无向/有向由
GraphEdges的graph_type控制,GraphNodes本身并不关心方向性。
在哪些视图中展示
依据 graph_nodes.md 的 "Can be shown in" 部分,GraphNodes可以在以下两种视图中展示:
- GraphView:专门的图可视化视图,支持有向/无向图渲染与力导向布局;
- DataframeView:表格视图,用于以行/列形式查看与查询节点数据。
GraphView 的布局与力学属性
GraphView 被标记为"不稳定类型"(可能在未来发生不向后兼容的变更),其核心属性包括:
background:图背景配置;visual_bounds:可视范围,范围内的内容保证可见(范围外可能因 letterbox 效应部分可见);force_link:控制由边连接的两个节点之间的相互作用力,含enabled(是否启用)、distance(目标距离)、iterations(每轮迭代应用次数);force_many_body:模拟节点两两之间的"电荷"斥力,含enabled、strength(强度);force_position:类似重力,把节点拉向指定位置,含enabled、strength、position;force_collision_radius:按节点半径解析节点间碰撞,含enabled、strength、iterations;force_center:尝试将图的重心移到原点,含enabled、strength。
当你不给GraphNodes设置positions时,正是这些力的组合在驱动节点自动布局。GraphView 可视化 archetype 的完整清单见 graph_view.md:GraphEdges与GraphNodes。
源码实现探秘:一个 archetype 如何贯通三门语言
GraphNodes的三种语言 API 并非手写,而是由re_types_builder依据同一份类型定义 graph_nodes.def.rs 生成,这保证了跨语言行为一致:
- Rust(crates/store/re_sdk_types/src/archetypes/graph_nodes.rs):实现了
re_types_core::Archetypetrait,提供descriptor_*()系列方法返回各字段的ComponentDescriptor,并通过from_arrow_components从 Arrow 数组反序列化;此外还提供了columns()/columns_of_unit_batches()辅助方法,可把组件批按长度切分为列,配合RecordingStream::send_columns直接发送列式(columnar)数据。 - Python(rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py):基于 attrs 定义
GraphNodes类,构造函数接收node_ids(Utf8ArrayLike)以及positions(Vec2DArrayLike)、colors(Rgba32ArrayLike)、labels(Utf8ArrayLike)、show_labels(BoolLike)、radii(Float32ArrayLike)等可选参数;类方法columns()支持rr.send_columns的列式写入,from_fields(clear_unset=...)支持按字段增量更新与整体清除。该文件头部注释还提示可通过创建GraphNodesExt扩展类自定义行为。 - C++(rerun_cpp/src/rerun/archetypes/graph_nodes.hpp):以结构体形式暴露字段(
std::optional<ComponentBatch>),提供with_positions、with_labels、with_colors、with_show_labels、with_radii等链式构造方法,以及update_fields()/clear_fields()静态方法。
值得留意的是,Rust 实现中每个字段的ComponentDescriptor都带有archetype = "rerun.archetypes.GraphNodes"与组件路径(如"GraphNodes:node_ids"、component_type = "rerun.components.GraphNode"),这构成了 Rerun 数据流中查询、索引与可视化匹配的基础——Viewer 正是通过这类描述符把记录数据路由到对应 visualizer(graph_nodes.rs 中可见VisualizableArchetype实现)。
实战建议与注意事项
- 务必保证节点 ID 一致:
GraphEdges的端点必须与GraphNodes的node_ids严格对应,否则边会因引用不存在的节点而无法渲染。建议在数据预处理阶段统一 ID 的规范化规则(如统一字符串格式)。 - 静态布局与自动布局的选择:如果数据本身带有空间语义(如机器人轨迹的拓扑、传感器拓扑图),显式传入
positions可获得确定性的坐标布局;如果只关心连接关系,省略positions交给GraphView的力导向布局(可调force_link/force_many_body/force_position等)往往更省事。 - 利用标签自动显隐:
show_labels缺省时会按"单标签实体或实例数低于阈值"的规则自动显示,节点规模大时无需手动处理;需要强制开关时再显式设置。 - 批量写入考虑
columns():当图结构随时间变化(时间序列图)时,Python 的GraphNodes.columns()或 Rust 的columns()可以把每个时间步的节点状态组织为列式数据,用send_columns一次性下发,性能优于逐帧log。 - 验证渲染效果:仓库中已生成无向/有向图的参考录制文件 graph_undirected.rrd 与 graph_directed.rrd,可用 Rerun Viewer 打开对照你自己的渲染结果,快速排查位置、标签或边方向的问题。
总而言之,GraphNodes是 Rerun 图可视化的"节点半边":掌握它的 6 个字段、与GraphEdges的键值关联,以及GraphView的力学布局行为,你就能在 Rerun 中快速搭建起可交互、可查询的图结构数据看板,无论是简单拓扑、依赖关系图,还是机器人多模态数据中的关系网络。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考