vector_traits/
vector2.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2023, 2025 lacklustr@protonmail.com https://github.com/eadf
3
4// This file is part of vector-traits.
5
6use crate::prelude::*;
7use std::fmt::Debug;
8
9/// A workaround for Rust's limitations where external traits cannot be implemented for external types.
10///
11/// The `Approx` trait provides methods for performing approximate equality comparisons on types.
12/// It serves as a workaround for Rust's limitations, allowing you to implement approximate
13/// equality checks for types not originally designed with this capability.
14///
15/// This trait leverages the `approx` crate and its traits to perform approximate equality
16/// comparisons. The methods in this trait are wrappers around the corresponding methods provided
17/// by the `approx` crate.
18///
19pub trait Approx: HasXY {
20    /// Checks if two instances are nearly equal within a specified tolerance in ULPs (Units in the Last Place).
21    ///
22    /// This method delegates to the `approx::UlpsEq::ulps_eq` method, performing approximate equality checks
23    /// one time per coordinate axis.
24    fn is_ulps_eq(
25        self,
26        other: Self,
27        epsilon: <Self::Scalar as approx::AbsDiffEq>::Epsilon,
28        max_ulps: u32,
29    ) -> bool;
30
31    /// Checks if two instances are nearly equal within a specified absolute difference tolerance.
32    ///
33    /// This method delegates to the `approx::AbsDiffEq::abs_diff_eq` method, performing approximate equality checks
34    /// one time per coordinate axis.
35    fn is_abs_diff_eq(
36        self,
37        other: Self,
38        epsilon: <Self::Scalar as approx::AbsDiffEq>::Epsilon,
39    ) -> bool;
40}
41
42/// A basic two-dimensional vector trait, designed for flexibility in precision.
43///
44/// The `HasXY` trait abstracts over two-dimensional vectors, allowing for easy
45/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
46/// significant codebase modifications. It only provides the most basic vector interface.
47/// It is intended to be used in situations where you need a custom storage type of vectors.
48/// For example an FFI type.
49///
50/// Implementors of this trait can benefit from the ability to switch between different
51/// precision representations seamlessly, making it ideal for applications where varying
52/// precision levels might be desirable at different stages or configurations.
53///
54/// The associated `Scalar` type represents the scalar type (e.g., `f32` or `f64`) used
55/// by the vector.
56///
57pub trait HasXY: Sync + Send + Copy + Debug + Sized {
58    type Scalar: GenericScalar;
59    /// create a new instance of Self, note that this
60    /// creates a 3d vector if the instanced type is a 3d type
61    fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self;
62    fn x(self) -> Self::Scalar;
63    fn x_mut(&mut self) -> &mut Self::Scalar;
64    fn set_x(&mut self, val: Self::Scalar);
65    fn y(self) -> Self::Scalar;
66    fn y_mut(&mut self) -> &mut Self::Scalar;
67    fn set_y(&mut self, val: Self::Scalar);
68}
69
70/// A generic two-dimensional vector trait.
71///
72/// The `GenericVector2` trait abstracts over two-dimensional vectors, allowing for easy
73/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
74/// significant codebase modifications. It provides the common operations one would expect
75/// for 2D vectors, such as dot products, cross products, and normalization.
76///
77/// Implementors of this trait can benefit from the ability to switch between different
78/// precision representations seamlessly, making it ideal for applications where varying
79/// precision levels might be desirable at different stages or configurations.
80///
81/// The associated `Scalar` type represents the scalar type (e.g., `f32` or `f64`) used
82/// by the vector, and `Vector3` is the corresponding three-dimensional vector type.
83///
84/// Note: The actual trait functionality might vary based on the concrete implementations.
85pub trait GenericVector2:
86    HasXY
87    + Copy
88    + Approx
89    + PartialEq
90    + std::ops::Index<usize, Output = Self::Scalar>
91    + std::ops::IndexMut<usize, Output = Self::Scalar>
92    + std::ops::AddAssign
93    + std::ops::SubAssign
94    + std::ops::Neg<Output = Self>
95    + std::ops::Add<Self, Output = Self>
96    + std::ops::Sub<Self, Output = Self>
97    + std::ops::Mul<Self::Scalar, Output = Self>
98    + std::ops::Div<Self::Scalar, Output = Self>
99    + Into<[Self::Scalar; 2]>
100    + From<[Self::Scalar; 2]>
101{
102    // Associated constants
103    const ZERO: Self;
104    const ONE: Self;
105
106    type Vector3: GenericVector3<Scalar = Self::Scalar, Vector2 = Self>;
107    type Affine: Affine2D<Vector2 = Self>;
108    type Aabb: Aabb2<Vector = Self> + Into<Vec<Self>>;
109
110    fn new(x: Self::Scalar, y: Self::Scalar) -> Self;
111    fn splat(value: Self::Scalar) -> Self;
112    fn to_3d(self, z: Self::Scalar) -> Self::Vector3;
113    fn magnitude(self) -> Self::Scalar;
114    fn magnitude_sq(self) -> Self::Scalar;
115    fn dot(self, other: Self) -> Self::Scalar;
116    fn perp_dot(self, rhs: Self) -> Self::Scalar;
117    fn distance(self, rhs: Self) -> Self::Scalar;
118    fn distance_sq(self, rhs: Self) -> Self::Scalar;
119    fn normalize(self) -> Self;
120    fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self>;
121    fn min(self, rhs: Self) -> Self;
122    fn max(self, rhs: Self) -> Self;
123    /// Clamps the vector's components to be within the range defined by `min` and `max`.
124    ///
125    /// # Note
126    /// This implementation does **not** follow `nalgebra`'s convention for `clamp`.
127    /// In `nalgebra`, `clamp` is symmetric around zero.
128    /// In this implementation, `clamp` ensures that `self` is bounded by `min` and `max`
129    /// in a non-symmetric way: `self.min(max).max(min)`.
130    fn clamp(self, min: Self, max: Self) -> Self;
131    /// returns false on all inf or NaN values
132    fn is_finite(self) -> bool;
133}