geomath/
prelude.rs

1//!
2//! The prelude specifies most of the features provided by the objects of the framework.
3//! This goes from math properties to array conversion and vectors concatenation.
4//!
5
6/// Construct objects either filled with ones or zeros
7pub trait Initializer {
8    /// Object filled with zeros
9    fn zeros() -> Self;
10    /// Object filled with ones
11    fn ones() -> Self;
12}
13
14/// Fill an object with a value
15pub trait Reset<T> {
16    /// Fills an object with zeros
17    fn reset0(&mut self) -> &mut Self;
18    /// Fills a object with ones
19    fn reset1(&mut self) -> &mut Self;
20
21    /// Fills a object with a given value
22    fn reset(&mut self, val: &T) -> &mut Self;
23}
24
25/// Set an object from an array and convert an object onto an array
26pub trait Array<T> {
27    /// Convert the object to array
28    fn to_array(&self) -> T;
29    /// Set the object from array
30    fn set_array(&mut self, arr: &T) -> &mut Self;
31}
32
33/// Set an object from a vector and convert an object onto a vector
34pub trait Vector<T> {
35    /// Convert the object to vector
36    fn to_vector(&self) -> T;
37    /// Set the object from vector
38    fn set_vector(&mut self, arr: &T) -> &mut Self;
39}
40
41/// Split an object onto two part that can be concatenated or accessed separately
42///
43/// It aims to be the upper and lower parts of a vector or the upper diagonal and lower diagonal parts of a matrix.
44pub trait Split<T> {
45    /// Get the two parts of the split object
46    fn split(&self) -> [T; 2];
47    /// Concatenates two part to construct an object
48    fn concat(lhs: &T, rhs: &T) -> Self;
49    /// Get the first part of the object
50    fn upper(&self) -> T;
51    /// Get the second part of the object
52    fn lower(&self) -> T;
53    /// Set the first part of the object
54    fn set_upper(&mut self, val: &T) -> &mut Self;
55    /// Set the second part of the object
56    fn set_lower(&mut self, val: &T) -> &mut Self;
57}
58
59/// Operations between objects of a metric space
60///
61/// A metric space is considered as a space where it exists a norm based on dot product.
62/// It can be the metric operations between two vectors or matrices such as the distance or the magnitude.
63///
64/// **Note :** For matrices and vectors you can also use operators : `%` for distance, `|` for dot product, `!` for magnitude
65pub trait Metric where
66    Self: Copy {
67    /// Dot product of the two objects
68    fn dot(&self, other: &Self) -> f64;
69    /// Squared distance between the two objects
70    fn distance2(&self, other: &Self) -> f64;
71    /// Distance between the two objects
72    fn distance(&self, other: &Self) -> f64;
73    /// Squared magnitude of an object
74    fn magnitude2(&self) -> f64;
75    /// Magnitude of an object
76    fn magnitude(&self) -> f64;
77    /// Get the normalized vector, ie. vector with same direction and magnitude 1
78    fn normalized(&self) -> Self {
79        let mut ret = *self;
80        ret.set_normalized();
81        ret
82    }
83    /// Normalizes the vector, ie. sets magnitude to 1 without changing direction
84    fn set_normalized(&mut self) -> &mut Self;
85}
86
87/// Operations related to the angle of two vectors
88///
89/// Do not use theses features with zero vector since divisions with the magnitude are performed.
90pub trait Angle where
91    Self: Metric {
92    /// Cosine of the angle between the two vectors, non-oriented
93    fn cos(&self, rhs: &Self) -> f64 {
94        self.dot(rhs) / (self.magnitude() * rhs.magnitude())
95    }
96    /// Sine of the angle between the two vectors, non-oriented
97    fn sin(&self, rhs: &Self) -> f64 {
98        self.area(rhs) / (self.magnitude() * rhs.magnitude())
99    }
100    /// Area of the parallelepiped formed by two vectors, non-oriented
101    fn area(&self, rhs: &Self) -> f64;
102    /// Angle between two vectors, non-oriented
103    fn angle(&self, rhs: &Self) -> f64 {
104        self.cos(rhs).acos()
105    }
106}
107
108/// Stable cross product of two vectors
109pub trait Cross where
110    Self: Copy + Clone {
111    /// Get the cross product between two vectors
112    fn cross(&self, rhs: &Self) -> Self {
113        let mut ret = *self;
114        ret.set_cross(rhs);
115        ret
116    }
117    /// Set the cross product between two vectors
118    fn set_cross(&mut self, rhs: &Self) -> &mut Self;
119}
120
121/// Interpolations between two objects
122pub trait Interpolation {
123    /// Get linear interpolation
124    fn lerp(&self, other: &Self, s: f64) -> Self where
125        Self: Copy + Clone {
126        let mut ret = *self;
127        ret.set_lerp(other, s);
128        ret
129    }
130    /// Get cubic Hermite's interpolation, ie. with two tangent values
131    fn herp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> Self where
132        Self: Copy + Clone {
133        let mut ret = *self;
134        ret.set_herp(other, other1, other2, s);
135        ret
136    }
137
138    /// Get cubic Bezier's interpolation, ie. with two control points
139    fn berp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> Self where
140        Self: Copy + Clone {
141        let mut ret = *self;
142        ret.set_berp(other, other1, other2, s);
143        ret
144    }
145
146    /// Set the linear interpolation
147    fn set_lerp(&mut self, other: &Self, s: f64) -> &mut Self;
148    /// Set the Hermite's interpolation
149    fn set_herp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> &mut Self;
150    /// Set the Bezier's interpolation
151    fn set_berp(&mut self, other: &Self, other1: &Self, other2: &Self, s: f64) -> &mut Self;
152}
153
154/// Access the matrix as an array of rows ordered from left to right
155pub trait Rows<T> where
156    Self: std::marker::Sized + Initializer {
157    /// Get a matrix from rows array
158    fn from_rows(rows: &T) -> Self {
159        let mut ret = Self::zeros();
160        ret.set_rows(rows);
161        ret
162    }
163    /// Get the rows of a matrix
164    fn rows(&self) -> T;
165
166    /// Set the rows of a matrix
167    fn set_rows(&mut self, rows: &T) -> &mut Self;
168}
169
170/// Square matrices algebra
171pub trait Algebra<T> where
172    Self: std::marker::Sized + Copy + Clone,
173    T: std::marker::Sized + Copy + Clone {
174    /// Get the determinant of the matrix
175    fn determinant(&self) -> f64;
176
177    /// Get the inverse matrix
178    fn inverse(&self) -> Self {
179        let mut ret = *self;
180        ret.set_inverse();
181        ret
182    }
183
184    /// Get the transposed matrix
185    fn transposed(&self) -> Self {
186        let mut ret = *self;
187        ret.set_transposed();
188        ret
189    }
190
191    /// Get the adjugate matrix
192    fn adjugate(&self) -> Self {
193        let mut ret = *self;
194        ret.set_adjugate();
195        ret
196    }
197
198    /// Set inverse matrix
199    fn set_inverse(&mut self) -> &mut Self;
200
201    /// Set transposed matrix
202    fn set_transposed(&mut self) -> &mut Self;
203
204    /// Set adjugate matrix
205    fn set_adjugate(&mut self) -> &mut Self;
206}
207
208/// Coordinates accessors
209///
210/// Get and Set coordinates of 2D and 3D vectors.
211///
212/// ## Conventions
213/// A coherent naming convention between polar, cylindrical and spherical coordinates has been established.
214///
215/// ### Coordinates naming
216/// ![coordinates](https://github.com/samiBendou/geomath/raw/dev/media/coordinates_diagram.png)
217///
218/// **3D coordinates representation in geomath**
219///
220/// The four basic coordinates systems are represented
221/// * (x, y, z) the cartesian coordinates
222/// * (rho, phi, z) the polar/cylindrical coordinates
223/// * (r, phi, theta) the spherical coordinates
224///
225/// The traits are implemented such that there is no code repetition between the systems that have coordinates
226/// in common. For example, since the angle phi is common to polar and spherical coordinates
227/// systems it will be only defined in the `Polar` trait.
228///
229/// **Notes :**
230///
231/// * The value of phi remains the same in both polar/cylindrical and spherical coordinates systems
232/// * The value of r in the schema above is denoted `radius` in the code
233/// * The z coordinate is common to cartesian and cylindrical coordinates systems
234///
235/// ### Local basis
236/// You can generate vectors of the local basis of each coordinate system, the convention is described
237/// in the schemas bellow.
238///
239/// ![coordinates](https://github.com/samiBendou/geomath/raw/dev/media/local_%20basis_diagram.png)
240///
241pub mod coordinates {
242    /// Polar coordinates accessors
243    pub trait Polar {
244        /// Get a vector from polar coordinates
245        fn from_polar(rho: f64, phi: f64) -> Self;
246
247        /// Set a vector from polar coordinates
248        fn set_polar(&mut self, rho: f64, phi: f64) -> &mut Self;
249
250        /// Get a unit polar radial vector from angle
251        fn unit_rho(phi: f64) -> Self;
252
253        /// Get a unit tangent/prograde vector from angle
254        fn unit_phi(phi: f64) -> Self;
255
256        /// Get the rho coordinate
257        fn rho(&self) -> f64;
258
259        /// Get the phi coordinate
260        fn phi(&self) -> f64;
261
262        /// Set the rho coordinate
263        fn set_rho(&mut self, rho: f64) -> &mut Self;
264
265        /// Set the phi coordinate
266        fn set_phi(&mut self, phi: f64) -> &mut Self;
267    }
268
269    /// Cylindrical coordinates accessors
270    pub trait Cylindrical {
271        /// Get a vector from cylindrical coordinates
272        fn from_cylindrical(rho: f64, phi: f64, z: f64) -> Self;
273
274        /// Set a vector from cylindrical coordinates
275        fn set_cylindrical(&mut self, rho: f64, phi: f64, z: f64) -> &mut Self;
276    }
277
278    /// Spherical coordinates accessors
279    pub trait Spherical {
280        /// Get a vector from spherical coordinates
281        fn from_spherical(radius: f64, phi: f64, theta: f64) -> Self;
282        /// Set a vector from spherical coordinates
283        fn set_spherical(&mut self, radius: f64, phi: f64, theta: f64) -> &mut Self;
284        /// Get a unit spherical radial vector from angles
285        fn unit_radius(phi: f64, theta: f64) -> Self;
286        /// Get a unit tangent/normal vector from angles
287        fn unit_theta(phi: f64, theta: f64) -> Self;
288        /// Get the theta coordinate
289        fn theta(&self) -> f64;
290        /// Set the theta coordinates
291        fn set_theta(&mut self, theta: f64) -> &mut Self;
292    }
293
294    /// Homogeneous coordinates transforms
295    pub trait Homogeneous<T> {
296        /// Get a inhomogeneous vector from an homogeneous vector
297        ///
298        /// The inhomogeneous vector has the last component removed and the others
299        /// divided by the value of the last component of the homogeneous vector.
300        fn from_homogeneous(vector: &T) -> Self;
301
302        /// Get a vector transformed to an homogeneous vector
303        ///
304        /// It is the same vector but with a component with the value 1 added.
305        fn to_homogeneous(&self) -> T;
306    }
307}
308
309/// Transform matrix
310///
311/// Set and generate transform matrices.
312/// The transform matrices can represent common 2D and 3D geometrical operations such as translation, rotation, ...
313pub mod transforms {
314    use crate::prelude::Initializer;
315    use crate::vector::Vector3;
316
317    /// Translation matrix
318    pub trait Translation<T> where
319        Self: std::marker::Sized + Copy + Clone + Initializer {
320        /// Get a translation matrix from translation vector
321        fn from_translation(vector: &T) -> Self {
322            let mut ret = Self::zeros();
323            ret.set_translation(vector);
324            ret
325        }
326
327        /// Set a translation matrix from translation vector
328        fn set_translation(&mut self, vector: &T) -> &mut Self;
329    }
330
331    /// Rigid body matrix
332    ///
333    /// A rigid body transform is the combination of a rotation and a translation.
334    pub trait Rigid<U, T> where
335        Self: std::marker::Sized + Copy + Clone + Initializer {
336        /// Get a rigid body matrix from rotation matrix and translation vector
337        fn from_rigid(rotation: &U, vector: &T) -> Self {
338            let mut ret = Self::zeros();
339            ret.set_rigid(rotation, vector);
340            ret
341        }
342
343        /// Set a rigid body matrix from the given rotation matrix and translation vector
344        fn set_rigid(&mut self, rotation: &U, vector: &T) -> &mut Self;
345    }
346
347    /// Similarity matrix
348    ///
349    /// A similarity is the combination of a scaling, a rotation and a translation.
350    pub trait Similarity<U, T> where
351        Self: std::marker::Sized + Copy + Clone + Initializer {
352        /// Get a similarity matrix from scale factor, rotation matrix and translation vector
353        fn from_similarity(scale: f64, rotation: &U, vector: &T) -> Self {
354            let mut ret = Self::zeros();
355            ret.set_similarity(scale, rotation, vector);
356            ret
357        }
358
359        /// Set a similarity matrix from scale factor, rotation matrix and translation vector
360        fn set_similarity(&mut self, scale: f64, rotation: &U, vector: &T) -> &mut Self;
361    }
362
363    /// 2D rotations matrix
364    pub trait Rotation2 where
365        Self: std::marker::Sized + Copy + Clone + Initializer {
366        /// Get a rotation matrix from angle
367        fn from_rotation(angle: f64) -> Self {
368            let mut ret = Self::zeros();
369            ret.set_rotation(angle);
370            ret
371        }
372
373        /// Set a rotation matrix from angle
374        fn set_rotation(&mut self, angle: f64) -> &mut Self;
375    }
376
377    /// 3D rotations matrix
378    pub trait Rotation3 where
379        Self: std::marker::Sized + Copy + Clone + Initializer {
380        /// Get a rotation matrix from axis and angle
381        fn from_rotation(angle: f64, axis: &Vector3) -> Self {
382            let mut ret = Self::zeros();
383            ret.set_rotation(angle, axis);
384            ret
385        }
386
387        /// Get a rotation matrix around x-axis from given angle
388        fn from_rotation_x(angle: f64) -> Self {
389            let mut ret = Self::zeros();
390            ret.set_rotation_x(angle);
391            ret
392        }
393
394        /// Get a rotation matrix around y-axis from given angle
395        fn from_rotation_y(angle: f64) -> Self {
396            let mut ret = Self::zeros();
397            ret.set_rotation_y(angle);
398            ret
399        }
400
401        /// Get a rotation matrix around z-axis from given angle
402        fn from_rotation_z(angle: f64) -> Self {
403            let mut ret = Self::zeros();
404            ret.set_rotation_z(angle);
405            ret
406        }
407
408        /// Set a rotation matrix from axis and angle
409        fn set_rotation(&mut self, angle: f64, axis: &Vector3) -> &mut Self;
410
411        /// Set a rotation matrix around x-axis from given angle
412        fn set_rotation_x(&mut self, angle: f64) -> &mut Self;
413
414        /// Set a rotation matrix around y-axis from given angle
415        fn set_rotation_y(&mut self, angle: f64) -> &mut Self;
416
417        /// Set a rotation matrix around z-axis from given angle
418        fn set_rotation_z(&mut self, angle: f64) -> &mut Self;
419    }
420}