#2d-vector #vector-math #2d #geometry #vector

vector2math

使用标准类型执行 2D 向量几何操作的特征

33 个版本

0.14.2 2024 年 5 月 11 日
0.14.0 2023 年 8 月 31 日
0.13.1 2023 年 1 月 28 日
0.13.0 2021 年 3 月 30 日
0.4.0 2019 年 3 月 28 日

数学 中排名第 261

Download history 98/week @ 2024-04-16 1/week @ 2024-04-30 217/week @ 2024-05-07 20/week @ 2024-05-14 6/week @ 2024-05-21 19/week @ 2024-05-28 9/week @ 2024-06-04 13/week @ 2024-06-11 1/week @ 2024-06-18 127/week @ 2024-07-30

每月下载量 127 次
用于 fit_text

MIT 许可证

55KB
1K SLoC

描述

此库提供了使用 Rust 的内置类型或自定义类型执行 2D 向量几何操作的特征。

有关示例和用法详情,请参阅 API 文档


lib.rs:

该包提供使用标准类型执行 2D 向量几何操作的特征

标量

以下标量类型的向量实现了简单的向量数学

  • u8-u128
  • usize
  • i8-i128
  • isize
  • f32
  • f64
  • 实现 Scalar 的任何类型

f32f64 实现 FloatingScalar,这为浮点数提供了额外的操作。

每个标量类型都有一个关联的模块,该模块使用该标量定义了标准几何类型的类型定义。

例如,而不是编写

let square = <[f32; 4]>::square([0.0; 2], 1.0);

你可以改写为

let square = f32::Rect::square([0.0; 2], 1.0);

向量

向量可以是以下形式

  • [T; 2]
  • (T,T)
  • 实现 Vector2 的任何类型

支持许多 2D 向量操作。

use vector2math::*;

let a = [2, 6];
let b = [4, -1];
assert_eq!(2, a.x());
assert_eq!(-1, b.y());
assert_eq!([-2, -6], a.neg());
assert_eq!([6, 5], a.add(b));
assert_eq!([-2, 7], a.sub(b));
assert_eq!([12, -3], b.mul(3));
assert_eq!([8, -6], b.mul2(a));
assert_eq!([1, 3], a.div(2));
assert_eq!([0, -6], a.div2(b));
assert_eq!(2, a.dot(b));

实现 FloatingVector2 的向量有额外的操作

use vector2math::*;

assert_eq!(5.0, [3.0, 4.0].mag());
assert_eq!(10.0, [-1.0, -2.0].dist([5.0, 6.0]));
let rotation_calculation = [1.0, 0.0].rotate_about(f64::TAU / 8.0, [0.0; 2]);
let rotation_solution = [2f64.powf(0.5) / 2.0; 2];
assert!(rotation_calculation.sub(rotation_solution).mag() < std::f64::EPSILON);

矩形

可以使用许多类型来定义轴对齐的矩形

  • [[T; 2]; 2]
  • [(T,T); 2]
  • ((T,T), (T,T))
  • ([T; 2], [T; 2])
  • [T; 4]
  • (T,T,T,T)
  • 任何实现了Pair的类型,其中关联的Pair::Item类型实现了Vector2
use vector2math::*;

let rect = [1i32, 2, 4, 6];
assert_eq!([1, 2], rect.top_left());
assert_eq!([4, 6], rect.size());
assert_eq!([3, 5], rect.center());
assert_eq!(20, rect.perimeter());
assert_eq!(24, rect.area());
assert!(rect.contains([3, 5]));
let corners = rect.corners();
assert_eq!(corners[0], [1, 2]);
assert_eq!(corners[1], [5, 2]);
assert_eq!(corners[2], [5, 8]);
assert_eq!(corners[3], [1, 8]);

一些类型可以用来定义圆

use vector2math::*;
use std::f64;

let circle = ([2.0, 3.0], 4.0);
assert!((circle.circumference() - 25.132_741_228_718_345).abs() < f64::EPSILON);
assert!((circle.area() - 50.265_482_457_436_69).abs() < f64::EPSILON);
assert!(circle.contains([0.0, 1.0]));
assert!(!circle.contains([5.0, 6.0]));

映射

向量、矩形和圆类型可以轻松映射到其他类型

use vector2math::*;

let arrayf32: [f32; 2] = [1.0, 2.0];
let arrayf64: [f64; 2] = arrayf32.map_into();
let pairf64: (f64, f64) = arrayf64.map_into();
let arrayi16: [i16; 2] = pairf64.map_with(|f| f as i16);
assert_eq!(arrayf32, arrayi16.map_into::<f32::Vec2>());

let weird_rect = [(0.0, 1.0), (2.0, 5.0)];
let normal_rectf32: [f32; 4] = weird_rect.map_into();
let normal_rectf64: [f64; 4] = normal_rectf32.map_into();
let normal_rectu8: [u8; 4] = normal_rectf32.map_with(|f| f as u8);
assert_eq!([0, 1, 2, 5], normal_rectu8);

let pair_circlef32 = ((0.0, 1.0), 2.0);
let array_circlef32 = ([0.0, 1.0], 2.0);
assert_eq!(((0.0, 1.0), 2.0), array_circlef32.map_into::<((f64, f64), f64)>());

变换

Transform特质用于定义2D向量变换。这个crate为所有实现了Pair的类型实现了Transform,其中PairItem实现了Trio,其中TrioTrio::Item实现了FloatingScalar。这个类型范围包括从[[f32; 3]; 2](f64, f64, f64, f64, f64, f64)的所有类型。Transform可以串联并应用于向量。

use vector2math::*;

let dis = [1.0; 2];
let rot = f32::TAU / 4.0;
let sc = [2.0; 2];

let transform = f32::Trans::identity().translate(dis).rotate(rot).scale(sc);

let v = [3.0, 5.0];
let v1 = v.transform(transform);
let v2 = v.add(dis).rotate(rot).mul2(sc);

assert_eq!(v1, v2);

实现特质

为您的类型实现这些特质很简单。只需确保您的类型是Copy

use vector2math::*;

#[derive(Clone, Copy)]
struct MyVector {
x: f64,
y: f64,
}

impl Vector2 for MyVector {
type Scalar = f64;
fn new(x: f64, y: f64) -> Self {
MyVector { x, y }
}
fn x(&self) -> f64 {
self.x
}
fn y(&self) -> f64 {
self.y
}
}

#[derive(Clone, Copy)]
struct MyRectangle {
top_left: MyVector,
size: MyVector,
}

impl Rectangle for MyRectangle {
type Vector = MyVector;
fn new(top_left: MyVector, size: MyVector) -> Self {
MyRectangle { top_left, size }
}
fn top_left(self) -> MyVector {
self.top_left
}
fn size(self) -> MyVector {
self.size
}
}

let rect: MyRectangle = [1, 2, 3, 4].map_into();
assert_eq!(12.0, rect.area());
assert_eq!(6.0, rect.bottom());

依赖

~230KB