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/// 
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/// 
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}