news 2026/9/16 22:08:39

Rerun UVec2D 编码类型详解:uint32 二维向量的定义、Arrow 数据布局与三语言实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rerun UVec2D 编码类型详解:uint32 二维向量的定义、Arrow 数据布局与三语言实现

Rerun UVec2D 编码类型详解:uint32 二维向量的定义、Arrow 数据布局与三语言实现

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

UVec2D 是 Rerun 数据模型(Data Model)中定义在encodings命名空间下的基础编码类型,表示一个由两个 32 位无符号整数(uint32)构成的二维向量,常用于表示非负整数类型的坐标、尺寸或索引。本文基于 Rerun 开源仓库中的类型定义文档与源码实现,系统讲解 UVec2D 的语义、底层 Arrow 数据布局(FixedSizeList(2 x non-null UInt32)),以及它在 Rust / Python / C++ 三种 SDK 中的构造方式、便捷方法与互转能力,帮助你理解 Rerun 类型系统的生成机制与序列化约定。

类型定位:数据模型中的"编码(Encoding)"基础类型

Rerun 的数据模型在 crates/store/re_sdk_types/src/encodings/mod.rs 中集中声明了一批与rerun.encodings.*对应的基础编码类型,包括Vec2DDVec2DIVec3DUVec3DUVec4D以及本文主角UVec2D等。这些类型并非某个具体可视化组件的专属字段,而是数据模型层面的通用"积木"——它们定义了某种结构化数据在内存与 Arrow 列式存储中的标准表示方式,可被上层组件(Component)与蓝图(Blueprint)复用。

从类型定义文档 docs/content/reference/types/encodings/uvec2d.md 可以确认其官方语义:

UVec2D:A uint32 vector in 2D space.

即"二维空间中的一个 uint32 向量"。选择uint32而非int32(对应IVec3D这类有符号类型)或float(对应Vec2D/DVec2D),意味着该类型面向的是一组天然为非负整数的二维数据,例如像素尺寸、栅格坐标、计数索引等场景。

该文档属于自动生成(auto-generated)的类型参考页,其原始定义位于类型定义源文件 crates/build/re_type_definitions/rerun/encodings/uvec2d.def.rs:

// This is a Rerun type definition for the SDK, not executable code. // It is parsed by `re_types_builder` to generate the Rust, Python and C++ bindings. /// A uint32 vector in 2D space. #[rerun::rerun_type] #[arrow(transparent)] #[python(aliases = "npt.NDArray[Any] | npt.ArrayLike | Sequence[int]")] #[python( array_aliases = "npt.NDArray[Any] | npt.ArrayLike | Sequence[Sequence[int]] | Sequence[int]" )] #[rust(derive(Default, Copy, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable))] #[rust(repr = "C")] #[rust(tuple_struct)] #[rerun(state = "stable")] pub struct UVec2D { pub xy: [u32; 2], }

从这份定义可以看出 Rerun 类型系统的几个关键设计:

  • 单一事实来源(Single Source of Truth).def.rs是供re_types_builder解析的类型定义(而非可执行代码),Rust、Python、C++ 三种 SDK 的绑定全部由它生成,保证三语言语义一致;
  • #[arrow(transparent)]:声明该类型在 Arrow 层采用"透明"布局——不额外包一层 struct,直接映射为定长列表;
  • #[rust(repr = "C")]+tuple_struct:生成的 Rust 结构体使用 C 内存布局的元组结构体,为bytemuck零拷贝转换(Pod/Zeroable)与跨 FFI 边界传递创造条件;
  • #[rerun(state = "stable")]:标记该类型处于稳定状态,说明其数据布局与序列化格式已被视为公共接口的一部分。

Arrow 数据布局:FixedSizeList(2 x non-null UInt32)

类型参考文档 uvec2d.md 明确给出了 UVec2D 对应的 Arrow 数据类型:

FixedSizeList(2 x non-null UInt32)

这一布局在生成的 Rust 绑定 crates/store/re_sdk_types/src/encodings/uvec2d.rs 中有完全一致的实现:

impl ::re_types_core::ArrowDataType for UVec2D { #[inline] fn arrow_data_type() -> arrow::datatypes::DataType { use arrow::datatypes::*; DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::UInt32, false)), 2, ) } }

其含义可以拆解为:

组成部分含义
FixedSizeList定长列表,每个元素固定包含 2 个子元素,存储紧凑、无需单独的长度字段
UInt32子元素为 32 位无符号整数(u32
non-nullField::new("item", …, false)false子元素不允许为 null,保证每个[x, y]都完整有效

序列化路径(ToArrow在 uvec2d.rs 中实现:先将每个UVec2D实例取其内部的[u32; 2]元组字段,展平为连续的u32值数组,再包装为FixedSizeListArray(内层是PrimitiveArray<UInt32Type>),外层无 validity 位图(即无 null 元素)。这种"展平 + 定长切片"的布局让整批数据在内存中连续排布,利于批量处理与按值拷贝。

反序列化路径(FromArrow在 uvec2d.rs 中实现,并带有严格的健壮性校验:

  • 首先调用err_on_nulls(arrow_data, "rerun.encodings.UVec2D"),拒绝包含 null 的数据;
  • 将输入强制转换为FixedSizeListArray,并校验value_length() == 2,不匹配即返回DeserializationError::datatype_mismatch
  • 最后通过bytemuck::try_cast_slice将连续的u32缓冲零拷贝重解释为[u32; 2]切片,逐个构造UVec2D实例。

可见 UVec2D 在序列化/反序列化两侧都做到了无逐元素复制,直接复用 Arrow 的连续缓冲,这与#[repr(C)]+Pod的派生是配套的设计。

Rust 侧 API:常量、访问器与互操作

Rust 的UVec2D分为自动生成部分与手工扩展部分(_ext.rs)。生成的类型本体见 crates/store/re_sdk_types/src/encodings/uvec2d.rs:

pub struct UVec2D(pub [u32; 2usize]);

派生了Clone, Debug, Default, Copy, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable, SizeBytes,并实现了From<[u32; 2usize]>From<UVec2D> for [u32; 2usize]的双向转换。

手工扩展部分位于 crates/store/re_sdk_types/src/encodings/uvec2d_ext.rs,提供了日常使用所需的便捷 API:

  • 常量UVec2D::ZERO(加法单位元[0, 0])与UVec2D::ONE(乘法单位元[1, 1]);
  • 构造UVec2D::new(x: u32, y: u32)const fn可在常量上下文中使用;
  • 访问器x()/y()分别返回索引 0 与索引 1 的分量,set_x()/set_y()用于赋值;
  • 便捷转换From<(u32, u32)>From<&(u32, u32)>From<&[u32; 2]>From<&Self>一应俱全——源码注释特别说明,这些 by-ref 转换是为了让使用者在处理切片时无需手动解引用即可完成Into/IntoIterator链式转换;
  • 索引:实现std::ops::Index(基于std::slice::SliceIndex<[u32]>),支持v[0]v[1]等切片式下标访问;
  • 显示:实现Display,输出格式为[x, y],便于日志与调试;
  • glam 互操作(feature "glam" 启用时):与游戏/图形常用数学库glam::UVec2双向互转——From<UVec2D> for glam::UVec2from_slice)与From<glam::UVec2> for UVec2Dto_array),使 UVec2D 可以直接接入图形学管线。

Python 侧 API:NumPy 兼容与类型别名

Python 绑定由 rerun_py/rerun_sdk/rerun/encodings/uvec2d.py 与扩展 rerun_py/rerun_sdk/rerun/encodings/uvec2d_ext.py 组成。

生成的类UVec2D是一个基于attrs的定长二维向量封装:

@define(init=False) class UVec2D(UVec2DExt): """**Encoding**: A uint32 vector in 2D space.""" def __init__(self: Any, xy: UVec2DLike) -> None: self.__attrs_init__(xy=xy) xy: npt.NDArray[np.uint32] = field(converter=to_np_uint32)

关键点:

  • 唯一的字段xy经过to_np_uint32转换器强制归一为npt.NDArray[np.uint32],即传入 Pythonint列表、NumPy 数组均可,最终统一为uint32的 NumPy 数组;
  • 实现了__array__(支持np.asarray(uvec2d)直接转 NumPy 数组)与__len__(恒为 2),与 NumPy 生态无缝协作;
  • 类型别名体系完整:UVec2DLike = UVec2D | npt.NDArray[Any] | npt.ArrayLike | Sequence[int]表示单个实例的合法输入;UVec2DArrayLike进一步覆盖"多个实例"的批量输入(Sequence[UVec2DLike] | Sequence[Sequence[int]]等),可参见 uvec2d.py。

批量对象UVec2DBatch通过_ARROW_DATATYPE = pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={}), 2)与 Python 侧 Arrow 类型对齐,其_native_to_pa_array委托给扩展类UVec2DExt.native_to_pa_array_override(见 uvec2d_ext.py):

@staticmethod def native_to_pa_array_override(data: UVec2DArrayLike, data_type: pa.DataType) -> pa.Array: points = flat_np_uint32_array_from_array_like(data, 2) return pa.FixedSizeListArray.from_arrays(points, type=data_type)

其中flat_np_uint32_array_from_array_like(data, 2)负责把任意形状的类数组输入展平为末尾维度为 2 的uint32数组,再交给pa.FixedSizeListArray.from_arrays组装成定长列表,与 Rust 侧的"展平 + FixedSizeList"序列化策略完全对应。

C++ 侧 API:聚合结构体与 Loggable 特化

C++ 绑定位于 rerun_cpp/src/rerun/encodings/uvec2d.hpp(扩展部分来自 uvec2d_ext.cpp):

namespace rerun::encodings { struct UVec2D { std::array<uint32_t, 2> xy; // extensions from uvec2d_ext.cpp: UVec2D(uint32_t x, uint32_t y) : xy{x, y} {} explicit UVec2D(const uint32_t* xy_) : xy{xy_[0], xy_[1]} {} uint32_t x() const { return xy[0]; } uint32_t y() const { return xy[1]; } // generated code: UVec2D() = default; UVec2D(std::array<uint32_t, 2> xy_) : xy(xy_) {} UVec2D& operator=(std::array<uint32_t, 2> xy_) { xy = xy_; return *this; } }; }

要点:

  • 底层存储是std::array<uint32_t, 2>,与 Rust 的[u32; 2]一一对应;
  • 提供(x, y)uint32_t*指针两种扩展构造函数,以及x()/y()访问器;
  • rerun命名空间下特化了Loggable<encodings::UVec2D>,其ComponentType字符串为"rerun.encodings.UVec2D",并通过arrow_data_type()to_arrow()fill_arrow_array_builder()三个接口完成 Arrow 序列化,与 Rust / Python 侧形成三语言对等的encodings类型注册体系。

与同族向量类型的区分

从 encodings/mod.rs 的导出列表可以看到,Rerun 的 encodings 模块同时提供了多个向量族类型。UVec2D 与它们的差异可以从类型定义源码直接确认:

类型维度元素类型典型语义
Vec2D2Df32浮点二维向量
DVec2D2Df64双精度浮点二维向量
IVec3D3Di32有符号整型三维向量
UVec2D2Du32无符号整型二维向量(本文)
UVec3D3Du32无符号整型三维向量
UVec4D4Du32无符号整型四维向量

选择建议:当二维数据本质上不允许出现负数(例如尺寸、像素坐标、计数)时优先使用UVec2D;若需要负坐标或小数坐标,则应改用IVec3D同族的带符号整型类型或Vec2D/DVec2D浮点类型。这种"按语义选类型"的约定也正是 Rerun 类型系统将编码类型细分化的目的所在。

小结

  • 语义UVec2D表示二维空间中的一个uint32向量,官方描述为 "A uint32 vector in 2D space",属于rerun.encodings.*命名空间下的稳定(stable)编码类型;
  • 数据布局:Arrow 层为FixedSizeList(2 x non-null UInt32),序列化采用"展平为连续u32缓冲 + 定长列表"的零拷贝友好策略,反序列化带 null 校验与长度校验;
  • 跨语言一致性:类型由 uvec2d.def.rs 单一来源定义,自动生成 Rust(uvec2d.rs + uvec2d_ext.rs)、Python(uvec2d.py + uvec2d_ext.py)、C++(uvec2d.hpp)三套绑定,三者共享相同的语义与 Arrow 布局;
  • 上手方式:Rust 用UVec2D::new(x, y)并支持与glam::UVec2互转;Python 用UVec2D([x, y])且可直接与 NumPy 互操作;C++ 用UVec2D(x, y)构造并经Loggable特化接入 Arrow 序列化。

如需进一步了解同族类型,可继续阅读 docs/content/reference/types/encodings/vec2d.md、dvec2d.md、uvec3d.md 与 uvec4d.md 等参考文档,以及 encodings 模块的完整源码 crates/store/re_sdk_types/src/encodings/mod.rs。

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 22:06:59

Pentagi:AI驱动的渗透测试自动化开发范式

1. “Pentagi”不是产品名&#xff0c;而是安全智能体开发范式的代号你搜“pentagi”&#xff0c;页面上跳出来的全是Docker、Neo4j、渗透测试、AI Agent——没有官网、没有GitHub仓库、没有文档首页&#xff0c;甚至没有一句官方定义。这很反常。我第一次看到这个词是在一个红…

作者头像 李华
网站建设 2026/9/16 22:05:00

JWT安全漏洞与防御实战:从算法混淆到密钥管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 22:04:47

img 图片裂图兜底:onerror 默认图降级与全局监听

线上页面上偶尔会冒出一张裂图&#xff1a;一个灰色小方块&#xff0c;或者浏览器自带的那枚破图标&#xff0c;旁边杵着一段 alt 文字。用户不会跟你说"这里 img 加载失败了"&#xff0c;他们只会说"你们这网站看着不太靠谱"。所以"img 图片找不到时…

作者头像 李华
网站建设 2026/9/16 22:03:03

联想电脑PE重装系统全攻略:从U盘制作到驱动排错

联想电脑 PE 重装系统玩电脑这些年&#xff0c;每次碰到系统卡死、蓝屏循环、开机进不去桌面这类问题&#xff0c;我第一反应不是用系统自带的"重置此电脑"&#xff0c;而是直接掏出U盘进PE重装系统。PE&#xff08;Preinstallation Environment&#xff0c;预安装环…

作者头像 李华
网站建设 2026/9/16 22:02:47

聚合支付自助接入实战:汇付天下签名验签与回调全流程详解

做支付开发这些年&#xff0c;我最大的感受是&#xff1a;业务再急&#xff0c;急不过接口文档&#xff1b;代码再简单&#xff0c;绕不开密钥签名。前段时间团队接了一个商场聚合支付项目&#xff0c;要求在一个商户号下同时收微信、支付宝、银联云闪付&#xff0c;还要支持刷…

作者头像 李华