speedy2d/
dimen.rs

1/*
2 *  Copyright 2021 QuantumBadger
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17use std::convert::TryInto;
18
19use num_traits::{AsPrimitive, Zero};
20use rusttype::Point;
21
22use crate::numeric::{PrimitiveZero, RoundFloat};
23
24/// A vector with two f32 values.
25pub type Vec2 = Vector2<f32>;
26
27/// A vector with two i32 values.
28pub type IVec2 = Vector2<i32>;
29
30/// A vector with two u32 values.
31pub type UVec2 = Vector2<u32>;
32
33/// A vector containing two numeric values. This may represent a size or
34/// position.
35#[repr(C)]
36#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
37pub struct Vector2<T>
38{
39    /// The horizontal component of the vector.
40    pub x: T,
41    /// The vertical component of the vector.
42    pub y: T
43}
44
45impl<T> Vector2<T>
46{
47    /// Instantiates a new `Vector2` from the specified horizontal and vertical
48    /// components.
49    #[inline]
50    #[must_use]
51    pub const fn new(x: T, y: T) -> Self
52    {
53        Vector2 { x, y }
54    }
55}
56
57impl<T: PrimitiveZero> Vector2<T>
58{
59    /// A constant representing a vector of zero magnitude. Each component is
60    /// set to zero.
61    pub const ZERO: Vector2<T> = Vector2::new(T::ZERO, T::ZERO);
62
63    /// Instantiates a new `Vector2` from the specified horizontal component,
64    /// setting the vertical component to zero.
65    #[inline]
66    #[must_use]
67    pub fn new_x(x: T) -> Self
68    {
69        Vector2 { x, y: T::ZERO }
70    }
71
72    /// Instantiates a new `Vector2` from the specified vertical component,
73    /// setting the horizontal component to zero.
74    #[inline]
75    #[must_use]
76    pub fn new_y(y: T) -> Self
77    {
78        Vector2 { x: T::ZERO, y }
79    }
80}
81
82impl<T> Vector2<T>
83where
84    T: Copy + std::ops::Mul<Output = T> + std::ops::Add<Output = T>
85{
86    /// Returns the magnitude of the vector, squared.
87    #[inline]
88    #[must_use]
89    pub fn magnitude_squared(&self) -> T
90    {
91        self.x * self.x + self.y * self.y
92    }
93}
94
95impl<T> Vector2<T>
96where
97    T: AsPrimitive<f32>
98        + Copy
99        + std::ops::Mul<Output = T>
100        + std::ops::Add<Output = T>
101        + std::ops::Div<f32, Output = T>
102{
103    /// Returns the magnitude of the vector.
104    #[inline]
105    #[must_use]
106    pub fn magnitude(&self) -> f32
107    {
108        (self.magnitude_squared().as_()).sqrt()
109    }
110
111    /// Normalizes the vector so that the magnitude is `1.0`. If the current
112    /// magnitude of the vector is `0.0`, then `None` is returned to avoid a
113    /// division by zero.
114    #[inline]
115    #[must_use]
116    pub fn normalize(&self) -> Option<Vector2<T>>
117    {
118        let magnitude = self.magnitude();
119
120        if magnitude.is_zero() {
121            return None;
122        }
123
124        Some(Vector2::new(self.x / magnitude, self.y / magnitude))
125    }
126}
127
128impl<T: std::ops::Neg<Output = T> + Copy> Vector2<T>
129{
130    /// Rotates the vector by 90 degrees in the clockwise direction.
131    #[inline]
132    #[must_use]
133    pub fn rotate_90_degrees_clockwise(&self) -> Vector2<T>
134    {
135        Vector2::new(-self.y, self.x)
136    }
137
138    /// Rotates the vector by 90 degrees in the anti-clockwise direction.
139    #[inline]
140    #[must_use]
141    pub fn rotate_90_degrees_anticlockwise(&self) -> Vector2<T>
142    {
143        Vector2::new(self.y, -self.x)
144    }
145}
146
147impl<T: num_traits::AsPrimitive<f32>> Vector2<T>
148{
149    /// Returns a new vector with each element cast to `f32`, using the `as`
150    /// operator.
151    #[inline]
152    #[must_use]
153    pub fn into_f32(self) -> Vec2
154    {
155        Vector2::new(self.x.as_(), self.y.as_())
156    }
157}
158
159impl<T: num_traits::AsPrimitive<i32>> Vector2<T>
160{
161    /// Returns a new vector with each element cast to `i32`, using the `as`
162    /// operator.
163    #[inline]
164    #[must_use]
165    pub fn into_i32(self) -> IVec2
166    {
167        Vector2::new(self.x.as_(), self.y.as_())
168    }
169}
170
171impl<T: num_traits::AsPrimitive<u32>> Vector2<T>
172{
173    /// Returns a new vector with each element cast to `u32`, using the `as`
174    /// operator.
175    #[inline]
176    #[must_use]
177    pub fn into_u32(self) -> UVec2
178    {
179        Vector2::new(self.x.as_(), self.y.as_())
180    }
181}
182
183impl<T: TryInto<i32>> Vector2<T>
184{
185    /// Attempts to convert each element of this vector to an `i32`, returning
186    /// an error if this fails.
187    #[inline]
188    pub fn try_into_i32(self) -> Result<IVec2, T::Error>
189    {
190        Ok(Vector2::new(self.x.try_into()?, self.y.try_into()?))
191    }
192}
193
194impl<T> From<(T, T)> for Vector2<T>
195where
196    T: Copy
197{
198    #[inline]
199    fn from(value: (T, T)) -> Self
200    {
201        Vector2::new(value.0, value.1)
202    }
203}
204
205impl<T> From<&(T, T)> for Vector2<T>
206where
207    T: Copy
208{
209    #[inline]
210    fn from(value: &(T, T)) -> Self
211    {
212        Vector2::new(value.0, value.1)
213    }
214}
215
216impl<T> From<&Self> for Vector2<T>
217where
218    T: Copy
219{
220    #[inline]
221    fn from(value: &Self) -> Self
222    {
223        *value
224    }
225}
226
227impl<T> From<&mut Self> for Vector2<T>
228where
229    T: Copy
230{
231    #[inline]
232    fn from(value: &mut Self) -> Self
233    {
234        *value
235    }
236}
237
238impl<T: Copy + std::ops::Add<Output = T>, R: Into<Self>> std::ops::Add<R> for Vector2<T>
239{
240    type Output = Vector2<T>;
241
242    #[inline]
243    fn add(self, rhs: R) -> Self::Output
244    {
245        let rhs = rhs.into();
246        Vector2::new(self.x + rhs.x, self.y + rhs.y)
247    }
248}
249
250impl<T: Copy + std::ops::Add<Output = T>, R: Into<Vector2<T>>> std::ops::Add<R>
251    for &Vector2<T>
252{
253    type Output = Vector2<T>;
254
255    #[inline]
256    fn add(self, rhs: R) -> Self::Output
257    {
258        let rhs = rhs.into();
259        Vector2::new(self.x + rhs.x, self.y + rhs.y)
260    }
261}
262
263impl<T: Copy + std::ops::Sub<Output = T>, R: Into<Self>> std::ops::Sub<R> for Vector2<T>
264{
265    type Output = Vector2<T>;
266
267    #[inline]
268    fn sub(self, rhs: R) -> Self::Output
269    {
270        let rhs = rhs.into();
271        Vector2::new(self.x - rhs.x, self.y - rhs.y)
272    }
273}
274
275impl<T: Copy + std::ops::Sub<Output = T>, R: Into<Vector2<T>>> std::ops::Sub<R>
276    for &Vector2<T>
277{
278    type Output = Vector2<T>;
279
280    #[inline]
281    fn sub(self, rhs: R) -> Self::Output
282    {
283        let rhs = rhs.into();
284        Vector2::new(self.x - rhs.x, self.y - rhs.y)
285    }
286}
287
288impl<T: Copy + std::ops::AddAssign, R: Into<Vector2<T>>> std::ops::AddAssign<R>
289    for Vector2<T>
290{
291    #[inline]
292    fn add_assign(&mut self, rhs: R)
293    {
294        let rhs = rhs.into();
295        self.x += rhs.x;
296        self.y += rhs.y;
297    }
298}
299
300impl<T: Copy + std::ops::AddAssign, R: Into<Vector2<T>>> std::ops::AddAssign<R>
301    for &mut Vector2<T>
302{
303    #[inline]
304    fn add_assign(&mut self, rhs: R)
305    {
306        let rhs = rhs.into();
307        self.x += rhs.x;
308        self.y += rhs.y;
309    }
310}
311
312impl<T: Copy + std::ops::SubAssign, R: Into<Vector2<T>>> std::ops::SubAssign<R>
313    for Vector2<T>
314{
315    #[inline]
316    fn sub_assign(&mut self, rhs: R)
317    {
318        let rhs = rhs.into();
319        self.x -= rhs.x;
320        self.y -= rhs.y;
321    }
322}
323
324impl<T: Copy + std::ops::SubAssign, R: Into<Vector2<T>>> std::ops::SubAssign<R>
325    for &mut Vector2<T>
326{
327    #[inline]
328    fn sub_assign(&mut self, rhs: R)
329    {
330        let rhs = rhs.into();
331        self.x -= rhs.x;
332        self.y -= rhs.y;
333    }
334}
335
336impl<T: Copy + std::ops::MulAssign> std::ops::MulAssign<T> for Vector2<T>
337{
338    #[inline]
339    fn mul_assign(&mut self, factor: T)
340    {
341        self.x *= factor;
342        self.y *= factor;
343    }
344}
345
346impl<T: Copy + std::ops::MulAssign> std::ops::MulAssign<T> for &mut Vector2<T>
347{
348    #[inline]
349    fn mul_assign(&mut self, factor: T)
350    {
351        self.x *= factor;
352        self.y *= factor;
353    }
354}
355
356impl<T: Copy + std::ops::DivAssign> std::ops::DivAssign<T> for Vector2<T>
357{
358    #[inline]
359    fn div_assign(&mut self, divisor: T)
360    {
361        self.x /= divisor;
362        self.y /= divisor;
363    }
364}
365
366impl<T: Copy + std::ops::DivAssign> std::ops::DivAssign<T> for &mut Vector2<T>
367{
368    #[inline]
369    fn div_assign(&mut self, divisor: T)
370    {
371        self.x /= divisor;
372        self.y /= divisor;
373    }
374}
375
376impl<T: Copy + std::ops::Mul<Output = T>> std::ops::Mul<T> for &Vector2<T>
377{
378    type Output = Vector2<T>;
379
380    #[inline]
381    fn mul(self, rhs: T) -> Self::Output
382    {
383        Vector2::new(self.x * rhs, self.y * rhs)
384    }
385}
386
387impl<T: Copy + std::ops::Mul<Output = T>> std::ops::Mul<T> for Vector2<T>
388{
389    type Output = Vector2<T>;
390
391    #[inline]
392    fn mul(self, rhs: T) -> Self::Output
393    {
394        Vector2::new(self.x * rhs, self.y * rhs)
395    }
396}
397
398impl<T: Copy + std::ops::Div<Output = T>> std::ops::Div<T> for &Vector2<T>
399{
400    type Output = Vector2<T>;
401
402    #[inline]
403    fn div(self, rhs: T) -> Self::Output
404    {
405        Vector2::new(self.x / rhs, self.y / rhs)
406    }
407}
408
409impl<T: Copy + std::ops::Div<Output = T>> std::ops::Div<T> for Vector2<T>
410{
411    type Output = Vector2<T>;
412
413    #[inline]
414    fn div(self, rhs: T) -> Self::Output
415    {
416        Vector2::new(self.x / rhs, self.y / rhs)
417    }
418}
419
420impl<T: RoundFloat> RoundFloat for Vector2<T>
421{
422    fn round(&self) -> Self
423    {
424        Vector2::new(self.x.round(), self.y.round())
425    }
426}
427
428impl<T> From<Point<T>> for Vector2<T>
429{
430    #[inline]
431    fn from(point: Point<T>) -> Self
432    {
433        Vector2::new(point.x, point.y)
434    }
435}
436
437#[cfg(test)]
438mod test
439{
440    use super::*;
441
442    #[test]
443    fn test_arithmetic()
444    {
445        assert_eq!(
446            Vector2::new(15, 20),
447            Vector2::new(10, 4) + Vector2::new(5, 16)
448        );
449
450        assert_eq!(
451            Vector2::new(5, -12),
452            Vector2::new(10, 4) - Vector2::new(5, 16)
453        );
454
455        assert_eq!(IVec2::new(-5, 10), IVec2::new(3, 10) - IVec2::new_x(8));
456
457        assert_eq!(IVec2::new(-5, 17), IVec2::new(-5, 10) + IVec2::new_y(7));
458    }
459
460    #[test]
461    fn test_arithmetic_ref()
462    {
463        assert_eq!(
464            Vector2::new(15, 20),
465            Vector2::new(10, 4) + &Vector2::new(5, 16)
466        );
467
468        assert_eq!(
469            Vector2::new(5, -12),
470            Vector2::new(10, 4) - &Vector2::new(5, 16)
471        );
472
473        assert_eq!(
474            Vector2::new(15, 20),
475            &Vector2::new(10, 4) + Vector2::new(5, 16)
476        );
477
478        assert_eq!(
479            Vector2::new(5, -12),
480            &Vector2::new(10, 4) - Vector2::new(5, 16)
481        );
482
483        assert_eq!(
484            Vector2::new(15, 20),
485            &Vector2::new(10, 4) + &Vector2::new(5, 16)
486        );
487
488        assert_eq!(
489            Vector2::new(5, -12),
490            &Vector2::new(10, 4) - &Vector2::new(5, 16)
491        );
492    }
493
494    #[test]
495    fn test_arithmetic_tuples()
496    {
497        assert_eq!(Vector2::new(15, 20), Vector2::new(10, 4) + (5, 16));
498
499        assert_eq!(Vector2::new(15, 20), Vector2::new(10, 4) + &(5, 16));
500
501        assert_eq!(Vector2::new(15, 20), &Vector2::new(10, 4) + (5, 16));
502
503        assert_eq!(Vector2::new(15, 20), &Vector2::new(10, 4) + &(5, 16));
504
505        assert_eq!(Vector2::new(5, -12), Vector2::new(10, 4) - (5, 16));
506
507        assert_eq!(Vector2::new(5, -12), Vector2::new(10, 4) - &(5, 16));
508
509        assert_eq!(Vector2::new(5, -12), &Vector2::new(10, 4) - (5, 16));
510
511        assert_eq!(Vector2::new(5, -12), &Vector2::new(10, 4) - &(5, 16));
512    }
513    #[test]
514    fn test_add_assign()
515    {
516        let mut left = Vector2::new(1, 2);
517        let right = Vector2::new(3, 4);
518        left += right;
519        assert_eq!(left, Vector2::new(4, 6));
520        left += &right;
521        assert_eq!(left, Vector2::new(7, 10));
522        {
523            let mut ref_left = &mut left;
524            ref_left += right;
525        }
526        assert_eq!(left, Vector2::new(10, 14));
527        {
528            let mut ref_left = &mut left;
529            ref_left += right;
530        }
531        assert_eq!(left, Vector2::new(13, 18));
532    }
533
534    #[test]
535    fn test_sub_assign()
536    {
537        let mut left = Vector2::new(9, 8);
538        let right = Vector2::new(1, 2);
539        left -= right;
540        assert_eq!(left, Vector2::new(8, 6));
541        left -= &right;
542        assert_eq!(left, Vector2::new(7, 4));
543        {
544            let mut ref_left = &mut left;
545            ref_left -= right;
546        }
547        assert_eq!(left, Vector2::new(6, 2));
548        {
549            let mut ref_left = &mut left;
550            ref_left -= right;
551        }
552        assert_eq!(left, Vector2::new(5, 0));
553    }
554
555    #[test]
556    fn test_mul_assign()
557    {
558        let mut left = Vector2::new(2, 3);
559        left *= 5;
560        assert_eq!(left, Vector2::new(10, 15));
561        {
562            let mut ref_left = &mut left;
563            ref_left *= 2;
564        }
565        assert_eq!(left, Vector2::new(20, 30));
566    }
567
568    #[test]
569    fn test_div_assign()
570    {
571        let mut left = Vector2::new(12, 8);
572        left /= 2;
573        assert_eq!(left, Vector2::new(6, 4));
574        {
575            let mut ref_left = &mut left;
576            ref_left /= 2;
577        }
578        assert_eq!(left, Vector2::new(3, 2));
579    }
580}