Skip to main content

smooth_frame/
geometry.rs

1use std::ops::{Add, Div, Mul, Neg, Sub};
2
3use crate::math::{clamp, EPSILON};
4
5/// 二维点。
6#[derive(Debug, Clone, Copy, PartialEq, Default)]
7pub struct Point {
8    /// X 坐标。
9    pub x: f64,
10    /// Y 坐标。
11    pub y: f64,
12}
13
14impl Point {
15    /// 创建一个二维点。
16    #[must_use]
17    pub const fn new(x: f64, y: f64) -> Self {
18        Self { x, y }
19    }
20
21    /// 判断坐标是否都是有限数值。
22    #[must_use]
23    pub fn is_finite(self) -> bool {
24        self.x.is_finite() && self.y.is_finite()
25    }
26}
27
28impl Add<Vector> for Point {
29    type Output = Point;
30
31    fn add(self, rhs: Vector) -> Self::Output {
32        Point::new(self.x + rhs.x, self.y + rhs.y)
33    }
34}
35
36impl Sub<Point> for Point {
37    type Output = Vector;
38
39    fn sub(self, rhs: Point) -> Self::Output {
40        Vector::new(self.x - rhs.x, self.y - rhs.y)
41    }
42}
43
44impl Sub<Vector> for Point {
45    type Output = Point;
46
47    fn sub(self, rhs: Vector) -> Self::Output {
48        Point::new(self.x - rhs.x, self.y - rhs.y)
49    }
50}
51
52/// 二维向量。
53#[derive(Debug, Clone, Copy, PartialEq, Default)]
54pub struct Vector {
55    /// X 分量。
56    pub x: f64,
57    /// Y 分量。
58    pub y: f64,
59}
60
61impl Vector {
62    /// 创建一个二维向量。
63    #[must_use]
64    pub const fn new(x: f64, y: f64) -> Self {
65        Self { x, y }
66    }
67
68    /// 判断分量是否都是有限数值。
69    #[must_use]
70    pub fn is_finite(self) -> bool {
71        self.x.is_finite() && self.y.is_finite()
72    }
73
74    /// 返回向量长度。
75    #[must_use]
76    pub fn length(self) -> f64 {
77        self.length_squared().sqrt()
78    }
79
80    /// 返回向量长度的平方。
81    #[must_use]
82    pub const fn length_squared(self) -> f64 {
83        self.x * self.x + self.y * self.y
84    }
85
86    /// 返回两个向量的点积。
87    #[must_use]
88    pub const fn dot(self, other: Vector) -> f64 {
89        self.x * other.x + self.y * other.y
90    }
91
92    /// 返回两个向量的二维叉积。
93    #[must_use]
94    pub const fn cross(self, other: Vector) -> f64 {
95        self.x * other.y - self.y * other.x
96    }
97
98    /// 返回单位向量;零长度或非有限向量返回 `None`。
99    #[must_use]
100    pub fn normalized(self) -> Option<Vector> {
101        let length = self.length();
102        if !length.is_finite() || length <= EPSILON {
103            return None;
104        }
105        Some(self / length)
106    }
107
108    /// 返回两个向量之间的夹角,单位为弧度。
109    #[must_use]
110    pub fn angle_between(self, other: Vector) -> Option<f64> {
111        let a = self.normalized()?;
112        let b = other.normalized()?;
113        Some(clamp(a.dot(b), -1.0, 1.0).acos())
114    }
115}
116
117impl Add for Vector {
118    type Output = Vector;
119
120    fn add(self, rhs: Vector) -> Self::Output {
121        Vector::new(self.x + rhs.x, self.y + rhs.y)
122    }
123}
124
125impl Sub for Vector {
126    type Output = Vector;
127
128    fn sub(self, rhs: Vector) -> Self::Output {
129        Vector::new(self.x - rhs.x, self.y - rhs.y)
130    }
131}
132
133impl Mul<f64> for Vector {
134    type Output = Vector;
135
136    fn mul(self, rhs: f64) -> Self::Output {
137        Vector::new(self.x * rhs, self.y * rhs)
138    }
139}
140
141impl Mul<Vector> for f64 {
142    type Output = Vector;
143
144    fn mul(self, rhs: Vector) -> Self::Output {
145        rhs * self
146    }
147}
148
149impl Div<f64> for Vector {
150    type Output = Vector;
151
152    fn div(self, rhs: f64) -> Self::Output {
153        Vector::new(self.x / rhs, self.y / rhs)
154    }
155}
156
157impl Neg for Vector {
158    type Output = Vector;
159
160    fn neg(self) -> Self::Output {
161        Vector::new(-self.x, -self.y)
162    }
163}