在 Rust 中声明 2D、3D 向量类型的惯用方法?

问题描述 投票:0回答:3

我正在寻找编写一些使用 2D 和 3D 点或空间方向的小型库
(向量/矩阵意义上的向量,而不是 Rust 的

Vec
)。

Rust 在这里没有强加规则,因此您可以创建一个浮点数元组,或者一个带有

struct
成员的新
x, y, z
。或单个
data: [f64; 3]
成员。

我想在这里定义类型而不是使用

[f64; 3]
的原因是我可以声明
length
normalized
Add
Sub
运算符等方法。

声明小型 2D - 3D 固定大小数据类型的良好基础是什么?


注意,虽然有很好的现有库,但我想编写自己的库,因为它只需要一些基本操作,而且我喜欢了解内部发生的情况。

types rust linear-algebra
3个回答
10
投票

你肯定应该使用一个库来做到这一点!有很多好的功能(见下文),即使您不使用所有功能,它们也大多不会产生任何开销。这会节省你很多时间,相信我。


但出于教育目的,这里有一些关于我如何设计这样一个库的想法。我认为 Rust 中的“惯用”。

  • 使用带有

    struct
    x
    y
    字段的
    z
    ,而不是数组或元组。这使得访问这些单独的标量变得非常自然,例如
    pos.x

  • 实现所有相关的运算符重载(例如

    std::ops
    ),以便您可以简单地添加和减去向量。

  • 提供有用且常用的方法,如

    length
    normalize

  • 除非它用于非常具体/狭窄的用例,否则您可能希望使标量类型通用。然后,您可能想要使用类似

    num_traits
    的东西来添加特征边界。

  • 您还可以尝试通过 const 泛型对不同的维度进行抽象,但这会让您的工作变得更加困难。

  • 使用强类型! Rust 是关于强类型的,所以要充分利用它。例如,区分点(位置)和矢量(位移)。也许还有方向(归一化向量)。当我们这样做时,对于以齐次坐标表示的点也有单独的类型。

但是,正确地完成所有这些工作需要时间和细心。我这样做了一次,最终得到了

lina
,我对此非常满意。尽管它还没有被广泛使用,并且对于某些人来说可能使用了太多的强类型。但正如我所说,还有许多其他好的库:
cgmath
nalgebra
,
glam
,
ultraviolet
vek
,还有更多!


2
投票

我建议定义一个newtype,即具有单个成员的元组结构。

struct Vector3D([f64; 3]); // wraps an array
struct Vector3D((f64, f64, f64)); // wraps a 3-tuple

元组结构体的字段可以通过使用它们的位置(从零开始)作为字段的名称来访问。例如,如果您有一个类型为

v
的变量
Vector3D
,则
v.0
将计算为内部字段。您可以选择公开或不公开该字段;要使其公开,请在字段类型名称之前添加关键字
pub

struct Vector3D(pub [f64; 3]);

请注意,这个新的

Vector3D
不会从包装类型继承任何方法或特征;您可以在该类型上提供您喜欢的任何 API。


1
投票

就像弗朗西斯所说,您可以使用包装类型,但如果您不需要它真正与其他类型区分开来并能够利用现有类型的方法,则可以使用类型别名:

type Vector3D = (f64, f64, f64);

type Vector3D = [f64; 3];
© www.soinside.com 2019 - 2024. All rights reserved.