rustvision/vec/
mod.rs

1//! Vectors in 2D space.
2
3mod vec2d;
4mod vec2i;
5
6use std::ops::{Add, Div, Mul, Sub};
7
8pub use self::vec2d::*;
9pub use self::vec2i::*;
10
11/// Struct for prepresenting a vector in 2D space.
12/// This vector features common operation such as addition, substraction and scaling
13/// (e.g., vector * scalar).
14///
15/// Unless you really know what you are doing, you should probably not use this struct directly.
16/// Rather work with the provided utility types (such as `Vec2d`).
17#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
18pub struct Vec2<T> {
19    pub x: T,
20    pub y: T,
21}
22
23/// Utility macro for creating a vector from the given arguments.
24///
25/// # Examples
26///
27/// You can create default (i.e., "zero length") vectors with this macro:
28///
29/// ```rust
30/// # #[macro_use] extern crate rustvision;
31/// use rustvision::vec::*;
32///
33/// let v = vec2![];
34/// assert_eq!(v, Vec2 { x: 0, y: 0 });
35/// ```
36///
37/// It also supports "prefilling" all fields of a vector with a given value:
38///
39/// ```rust
40/// # #[macro_use] extern crate rustvision;
41/// use rustvision::vec::*;
42///
43/// let v = vec2![42];
44/// assert_eq!(v, Vec2 { x: 42, y: 42 });
45/// ```
46///
47/// Lastly, it supports intuitive vector initialization aswell:
48///
49/// ```rust
50/// # #[macro_use] extern crate rustvision;
51/// use rustvision::vec::*;
52///
53/// let v = vec2![42, 1337];
54/// assert_eq!(v, Vec2 { x: 42, y: 1337 });
55/// ```
56///
57/// This macro is also "type agnostic" in a way, that automatically creates a vector of the fitting
58/// utility type (e.g., `Vec2d`) when called with the right arguments.
59#[macro_export]
60macro_rules! vec2 {
61    () => {
62        $crate::vec::Vec2::default()
63    };
64    ($val:expr) => {
65        $crate::vec::Vec2 { x: $val, y: $val }
66    };
67    ($x:expr, $y:expr) => {
68        $crate::vec::Vec2 { x: $x, y: $y }
69    };
70}
71
72/// Common operations on vectors.
73pub trait VectorOperations<T> {
74    /// Get the length of this vector.
75    fn length(&self) -> f64;
76
77    /// Normalize this vector (i.e., set its length to 1 but preserve the direction).
78    fn normalize(&self) -> Vec2<f64>;
79
80    /// Calculate the dot product of this vectort and another one.
81    fn dot(&self, rhs: &Self) -> T;
82}
83
84impl<T> Add for Vec2<T>
85where
86    T: Add<Output = T>,
87{
88    type Output = Self;
89
90    fn add(self, rhs: Self) -> Self::Output {
91        Self {
92            x: self.x + rhs.x,
93            y: self.y + rhs.y,
94        }
95    }
96}
97
98impl<T> Sub for Vec2<T>
99where
100    T: Sub<Output = T>,
101{
102    type Output = Self;
103
104    fn sub(self, rhs: Self) -> Self::Output {
105        Self {
106            x: self.x - rhs.x,
107            y: self.y - rhs.y,
108        }
109    }
110}
111
112impl<T> Mul<T> for Vec2<T>
113where
114    T: Mul<Output = T> + Clone + Copy,
115{
116    type Output = Self;
117
118    fn mul(self, rhs: T) -> Self::Output {
119        Self {
120            x: self.x * rhs,
121            y: self.y * rhs,
122        }
123    }
124}
125
126impl<T> Div<T> for Vec2<T>
127where
128    T: Div<Output = T> + Clone + Copy,
129{
130    type Output = Self;
131
132    fn div(self, rhs: T) -> Self::Output {
133        Self {
134            x: self.x / rhs,
135            y: self.y / rhs,
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn test_vec_add() {
146        assert_eq!(
147            Vec2 { x: 1, y: 0 } + Vec2 { x: 2, y: 1 },
148            Vec2 { x: 3, y: 1 }
149        );
150    }
151
152    #[test]
153    fn test_vec_sub() {
154        assert_eq!(
155            Vec2 { x: 1, y: 0 } - Vec2 { x: 2, y: 1 },
156            Vec2 { x: -1, y: -1 }
157        );
158    }
159
160    #[test]
161    fn test_vec_scale() {
162        assert_eq!(Vec2 { x: 2, y: 5 } * 3, Vec2 { x: 6, y: 15 });
163    }
164
165    #[test]
166    fn test_vec_div() {
167        assert_eq!(Vec2 { x: 2.0, y: 5.0 } / 2.0, Vec2 { x: 1.0, y: 2.5 });
168    }
169
170    #[test]
171    fn test_vec2_macro_empty() {
172        assert_eq!(vec2![], Vec2 { x: 0, y: 0 });
173    }
174
175    #[test]
176    fn test_vec2_macro_splat() {
177        assert_eq!(vec2![42], Vec2 { x: 42, y: 42 });
178    }
179
180    #[test]
181    fn test_vec2_macro_double_args() {
182        assert_eq!(vec2![3, 4], Vec2 { x: 3, y: 4 });
183    }
184}