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



我想写一些使用2D和3D点或空间方向的小库
(矢量/矩阵意义上的矢量,而不是Rust的Vec)。

Rust在这里没有强加规则,所以你可以创建一个浮点数元组,或者一个包含x, y, z成员的新struct。或单个data: [f64; 3]成员。

我想在这里定义类型而不是使用[f64; 3]的原因是,这样我就可以声明length, normalized, Add, Sub操作符等方法。

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

注意,虽然有很好的现有库,我想写我自己的,因为它只需要一些基本的操作,我想了解内部发生了什么。

这个问题相当宽泛,没有一个明确的最佳方式来表达你想要什么。这在很大程度上取决于你打算用它做什么。

与其他答案相比,我将提出一个稍微不同的解决方案:使用具有x, y, z组件的结构体,并充分使用强类型

向量可以用来表示很多东西(点,颜色,…);你谈论的是空间中的二维和三维点。首先要注意的是点矢量和方向矢量的区别。这里有一个很好的数学答案。Stackexchange很好地解释了这个话题。

这种差异可以反映在类型系统中,以捕获逻辑错误。这正是cgmath正在做的。所以我想说,你实际上想要两种类型像这样定义:

struct Point3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}
  • 为什么没有元组结构或数组?v.x的语义比v.0v[0]要清晰得多。如果您有一个表示任意数据的向量类型,后两种情况是合适的。但是正如我提到的,我认为强类型在这里是一个很好的选择,我们应该选择相应的好名字。
  • 为什么是pub ?为什么不是?如果您谈论的是空间中的点或方向,则不存在无效向量(此处忽略NaN浮动值)。所以没有理由限制对字段的访问。
  • 为什么是f32 ?好问题…实际上,你可能应该使用类型参数,但你需要有某种trait绑定…

…好吧,这就引出了我的结论,你可能不喜欢:我认为在这种情况下,要做到正确和"习惯"需要一些努力。像cgmath这样的库可以很好地完成这项工作。在我看来,这个cgmath库特别有一个非常好的API设计。大多数功能是通过特征(如VectorSpace)实现的,这些特征反映了背后的一些数学原理。我也想在我的一个项目中自己编写向量类型,但我最终被说服使用一个经过良好测试、设计良好的库来代替。


那么如何做到"正确"呢?cgmath差不多:

  • 强类型
  • 正确命名
  • 在抽象特征中具有最多的功能

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

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

元组结构的字段可以通过使用它们的位置(从零开始)作为字段名来访问。例如,如果有一个类型为Vector3D的变量v,则v.0将计算为内部字段。您可以选择将此字段设置为公共或不设置;要使其公开,只需在字段的类型名称之前添加关键字pub

struct Vector3D(pub [f64; 3]);

请注意,这个新的Vector3D不继承任何方法或特征从包装类型;这取决于你提供任何你喜欢的API在这个类型上

正如Francis所说,您可以使用包装器类型,但如果您不需要它与其他类型真正不同,并且能够利用现有类型的方法,则可以使用类型别名:

type Vector3D = (f64, f64, f64);

type Vector3D = [f64; 3];

相关内容

  • 没有找到相关文章

最新更新