Expand description
§Geometry library
This library provides for N-dimensional geometrical objects, particularly Vectors, Matrix, Quaternion operations.
The underlying numeric type that must be supported for these operations is either a type supporting Num - which includes integers - or in most circumstances Float. Particularly the latter is provided by f32 anf f64.
It provides libraries that provide functions that implement vector,
matrix and quaternion operations using arrays of values. For
quaternions this is [F; 4], in the order i, j, k, r.
It additionally provides traits for Vector, Quaternion, and
SqMatrix. These traits provide consistent means of manipulating such
items, which are expected to be in some manner a wrapper around a
[F;D], but with perhaps greater alignment restrictions. In theory
this could be a SIMD type.
The purpose of these traits is to provide simple access to the vector,
matrix, and quaternion operations using methods, rather than invoking
these operations through explicit function calls. For example,
quaternions can be multiplied together with a*b, rather than
invoking quat::multiply.
The library mirrors the operation of ‘glm’ in some sense.
The desire for the library is that it does not undergo much development; it provides a stable and simple basis for operations that are common mathematical operations, with no aim for it to grow into a larger linear algebra library.
§Caveats
The functions in the library use const generics, but as const generic
evaulations are currently unstable it requires more consts than should
be required. For example, to create an identity square matrix the
matrix::identity function has the generic signature <V:Num, const D2:usize, const D:usize>. The value of D2 must equal D*D. The
function returns [V; D2].
Ideally the function should just take D as a const generic argument
and the type would be [V;D*D], but that is unstable (and there are
some other issues).
Additionally, the inference of a type for V is sometimes required to
be forced, so there may be a small amount of turbofish notation such
as identity2::<f32>().
§Trait method policy
The purpose of the traits is to permit simple operation on arrays such
as [f32;4], without necessarily requiring conversion of those arrays
into a specific type first. For example, it is simple to add [1,2,3]
to a Vector type without having to convert that first into a Vector
type - but it must also work for any Vector type too. Hence the
arguments to methods are generally &[F; D].
However, for methods that return a (e.g.) Vector type (that is not
Self), this would force the caller to convert the resultant type back
to the required Vector type. The policy is therefore, for such
methods, to use a generic on the method T:Deref<Target = [}>; to
take an argument of type &T, and to return a T. This usually
requires T to also provide From<F;D>. These methods can be described
as ‘apply M to type T to produce a modified T’. In general there will
then be a method on the type T that operates on ‘&mut T’ and
explicitly takes a &M'. These methods also return &mut self` to
permit chaining.
For example, a matrix M can transform a vector T by using
use geo_nd::{FArray, FArray2, SqMatrix, Vector};
let t : FArray::<f32, 3> = [0.0, 1.0, 2.0].into();
let m = FArray2::<f32, 3, 9>::identity();
let mut t = m.transform(&t);
// or
t.transformed_by_m(&m);
The downside to this policy is that one cannot apply a matrix to transform an array [F;D]
use geo_nd::{FArray, FArray2, SqMatrix, Vector};
let m = FArray2::<f32, 3, 9>::identity();
let t = m.transform(&[1.0,3.0,5.0]);§Function operation
The functions for geometry manipulation are provided in the vector, [mat] and quat modules.
§Basic operation
use geo_nd::vector;
let y = [0., 1.];
let x = [1., 0.];
assert_eq!( vector::dot(&x, &y), 0., "Dot product of X and Y axis vectors is zero");
let xy = vector::add(x,&y,2.);
assert_eq!( xy, [1., 2.], "x + 2*y");
assert_eq!( vector::length_sq(&xy), (5.), "|x + 2*y|^2 = 5");
assert_eq!( vector::length(&xy), (5.0f64).sqrt(), "|x + 2*y| = sqrt(5)");§Provided traits
The library provides traits for types that can be vectors, matrices, and quaternions.
§Vector
Types that provide Vector can be manipulated with negation, addition, subtraction, and can be scaled with multiplication and division by their ‘float’; their components can be accessed through indexing (e.g. a[0]) immutably and mutably.
As non-traditional vector operations they can be piece-wise multiplied and divided also, which can be useful in graphcis applications; they can also be piece-wise added and subtracted from using their ‘float’.
They also support Copy, std::default::Default, std::fmt::Debug, and std::fmt::Display, serde::Serialize, serde::Deserialize.
They provide AsRef for float arrays of length 4 and slices for fast import and export from memory structures.
§Vector3
Vector3 types are 3-element vectors which additionally provide a [Vector3::cross_product] method, which does not exist (in a simply well defined manner) for other vector sizes.
§SqMatrix
Types that provide SqMatrix are square matrices that can be manipulated with negation, addition, subtraction, and multiplicaton, and can be scaled with multiplication and division by their ‘float’; their components can be accessed through indexing (e.g. a[0]) immutably and mutably. The index is a usize, in row-major order (i.e. [0] is row zero column zero, [1] is row 0 column 1, and [nr] is row 1 column 0 for a matrixt that is ‘nr’ by ‘nc’ rows by columns.)
They can also be piece-wise added and subtracted from using their ‘float’.
They also support Copy, std::default::Default, std::fmt::Debug, and std::fmt::Display, serde::Serialize, serde::Deserialize.
They provide AsRef for float arrays of length 4 and slices for fast import and export from memory structures.
§SqMatrix4
Types that provide SqMatrix4 are 4-by-4 matrices. Additional methods are provided for graphics operations, and so the matrices are treated as 3-by-3 transformation matrices with a translation vector and the last element the distance scaling.
They provide SqMatrix and additionally support graphically-useful constructors ‘perspective’ and ‘look_at’, and support translation by vectors.
§Quaternion
Quaternions are a mathematical means for describing a 3 dimensional rotation around the origin.
Types that provide Quaternion can be manipulated with negation, addition, subtraction, multiplicaton, and division, and can be scaled with multiplication and division by their ‘float’.
They also support Copy, std::default::Default, std::fmt::Debug, and std::fmt::Display, serde::Serialize, serde::Deserialize.
They Deref to their float arrays of length 4. The mapping of the arrays is (i, j, k, r).
§Constructors
Types providing the Quaternion trait can be constructed from:
-
a unit quaternion (1.0 + 0i + 0j + 0*k)
-
(r,i,j,k) tuples
-
the conjugate of another quaternion, i.e. (r,-i,-j,-k)
-
a rotation around a
[F; 3]axis by an angle (in radians) -
a rotation around one of the axes applied to another quaternion
-
another quaternion applied to a rotation around one of the axes
-
from a square matrix that describes a pure rotation (no scaling)
-
that describes a rotation of a camera looking down the negative Z axis with the Y axis as up, to one looking along a specified direction with a (perpendicular) up direction
-
the rotation that provides the shortest great circle path for one unit vector to another (the axis of the rotation is the perpendicular to both)
-
the weighted average of a number of quaternions
The trait provides many application methods for quaternions, perhaps the most important being Quaternion::apply3 and Quaternion::apply4, which allow the quaternion to be applied to a 3-element or 4-element vector (the latter being common in graphics, where the fourth element is usually 1 for a point, and 0 for a vector translation).
§Provided types
The library provides types that simply wrap f32 and f64 arrays,
providing imlpementations of the traits and hence supporting vectors, matrices and quaternions. This is perhaps the
simplest way to use the library.
§Vector types
The FArray type is a wrapper around an N-element array of floats, and it supports the Vector trait.
§SqMatrix types
The FArray2 type is a wrapper around an N-by-N-element array of floats, and it supports the SqMatrix trait.
§Quaternion types
The QArray type is a wrapper around an 4-element array of floats, and it supports the Quaternion trait.
§Examples
§Two dimensions
// Import the traits
use geo_nd::{Vector, SqMatrix};
// Aliases for the types
pub type Point2D = geo_nd::FArray<f64, 2>;
pub type Mat2x2 = geo_nd::FArray2<f64, 2, 4>;
let x : Point2D = [1.0, 0.0].into();
let y : Point2D = [0.0, 1.0].into();
let c = 30.0_f64.to_radians().cos();
let s = 30.0_f64.to_radians().sin();
let rot30 : Mat2x2 = [c, -s, s, c].into();
let rot60 = rot30 * rot30;
// Rotating x anticlockwise by 30 and 60 should turn it into y
let is_it_y = rot60.transform(&rot30.transform(&x));
// Check that the distance between them is tiny
assert!((y-is_it_y).length_sq() < 1.0E-8);
assert!(y.distance(&is_it_y) < 1.0E-8);
let rot90 = rot60 * rot30;
let rot180 = rot90 * rot90;
let xy = x + y;
let is_it_zero = xy + rot180.transform(&xy);
assert!(is_it_zero.length() < 1.0E-8);§Three dimensions
// Import the traits
use geo_nd::{Quaternion, SqMatrix, Vector};
// Aliases for the types
pub type Point3D = geo_nd::FArray<f64, 3>;
pub type Mat3x3 = geo_nd::FArray2<f64, 3, 9>;
pub type Point4D = geo_nd::FArray<f64, 4>;
pub type Quat = geo_nd::QArray<f64>;
let x : Point3D = [1., 0., 0.].into();
let y : Point3D = [0., 1., 0.].into();
let z : Point3D = [0., 0., 1.].into();
// qx rotates around the X axis by 90 degrees
// [X,0,0] is unchanged
// [0,1,0] maps to [0,0,1]
// [0,0,1] maps to [0,-1,0]
let qx = Quat::default().rotate_x(90.0_f64.to_radians());
assert!(z.distance(&y.apply_q3(&qx)) < 1.0E-8);
assert!(y.distance(&(-z).apply_q3(&qx)) < 1.0E-8);
assert!(x.distance(&(x).apply_q3(&qx)) < 1.0E-8);
// qy rotates around the Y axis by 90 degrees
// [1,0,0] maps to [0,0,-1]
// [0,Y,0] is unchanged
// [0,0,1] maps to [1,0,0]
let qy = Quat::default().rotate_y(90.0_f64.to_radians());
assert!(x.distance(&(z).apply_q3(&qy)) < 1.0E-8);
assert!(z.distance(&(-x).apply_q3(&qy)) < 1.0E-8);
assert!(y.distance(&(y).apply_q3(&qy)) < 1.0E-8);
// qx * qy applies qx to (qy applied to a vector)
// Hence this chains the qx mapping onto the qy mapping
// [1,0,0] -> [0,0,-1] -> [0,1,0]
// [0,1,0] -> [0,1,0] -> [0,0,1]
// [0,0,1] -> [1,0,0] -> [1,0,0]
//
// This is actually a 120 degree rotation around (1,1,1)
// (qy * qx is a 120 degree rotation around (1,-1,1))
let qxy = qx * qy;
assert!(y.distance(&(x).apply_q3(&qxy)) < 1.0E-8);
assert!(z.distance(&(y).apply_q3(&qxy)) < 1.0E-8);
assert!(x.distance(&(z).apply_q3(&qxy)) < 1.0E-8);
let mut m = Mat3x3::default();
qxy.set_rotation3(&mut m);
// qxy will be [0,0,1, 1,0,0, 0,1,0]
// give or take floating point errors
assert!((m.transform(&x) - y).length() < 1.0E-8);
assert!((m.transform(&y) - z).length() < 1.0E-8);
assert!((m.transform(&z) - x).length() < 1.0E-8);§Trait discussion
The libraries operate on arrays [F;D], and so types that implement
the Vector, Quaternion etc traits are expected to be wrappers around
such array (but perhaps with greater alignment restrictions).
An array [f32/f64; D] supports:
-
Copy, Clone, Debug, Default, PartialEq, PartialOrd
-
Index
and IndexMut -
IntoIterator for T, &T, &mut T
-
PartialEq of
[U;N]and[U](where T: PartialEq of U) -
TryFrom of
&[T],Vec<T, A>,Box<[T]>with mut where appropriate; some times for&[F; D]too -
AsRef[T], Borrow[T] (and mut for those three)
-
Serialize, Deserialize
Note: Hash is not supported as f32/f64 do not support it
Hence a Vector or Quaternion should provide:
-
Copy, Clone, Debug, Default, PartialEq
-
Index
and IndexMut -
Deref <Target =
[F; D]>, DerefMut -
AsRef and AsMut of
[F; D] -
From of
&[F],[F;D],&[F;D] -
Into
[F;D](deref provides equivalent of &[F; D]) -
TryFrom of
&[F],Vec<F> -
Serialize, Deserialize
Note: Not PartialOrd, as vectors dont’t have an ordering
Addition/Subtraction/Multiplication/Division
Add/Sub with Rhs of Self, &Self, Deref<Target = [F;D]> are required for utility; we cannot require the last of these, as Rust has no syntax for that.
Mul/Div with Rhs of F, &F are required for utility; previous versions supported Self to do element-wise operations, which has been removed This is in part because it would need to work for Deref<Target = [F;D]>, but f32/f64 do not implement Deref, and they might in the future do so which breaks the F and &F operation.
Not AsRef/Mut of [F], as [F; D] implement that, and Vector gets it through Deref
Note AsRef<[F]> is implemented through Deref to [F; D]
Note AsMut<[F]> is implemented through DerefMut to [F; D]
if required, then it blocks Add<Deref<Target = [F;D]>> !
Modules§
- glsl
- The glsl module is a place-holder for types that are compatible with GLSL
- matrix
- Matrix library
- quat
- Quaternion module
- vector
- Vector functions module
Structs§
- FArray
- The FArray is a wrapper around a
Dsized array of Floats. - FArray2
- The FArray2 is a wrapper around a
D2 = D^2` sized array of Floats. - FQArray
Trans - A transformation that is a translation . scaling . rotation (i.e. it applies the rotation to an object, then scales it, then translates it)
- QArray
- The QArray is a wrapper around a
Dsized array of Floats.
Traits§
- Float
- The Float trait is required for matrix or vector elements which
have a float aspect, such as
sqrt. - Geometry2D
- This is an experimental trait - it bundles together a Vec2 and a Mat2.
- Geometry3D
- The Geometry3D trait supplies a framework for implementing 3D vector and matrix operations, and should also include the quaternion type.
- Num
- The Num trait is required for matrix or vector elements; it is not a float, and so some of the matrix and vector operations can operate on integer types such as i32, i64 and isize
- Quaternion
- The Quaternion trait describes a 4-dimensional vector of Float type.
- SqMatrix
- The SqMatrix trait describes an N-dimensional square matrix of Float type that operates on a Vector.
- SqMatrix2
- The SqMatrix2 trait describes a 2-dimensional vector of Float
- SqMatrix3
- The SqMatrix3 trait describes a 2-dimensional vector of Float
- SqMatrix4
- The SqMatrix4 trait describes a 2-dimensional vector of Float
- Transform
- The Transform trait describes a translation, rotation and scaling for 3D, represented eventually as a Mat4
- Vector
- The Vector trait describes an N-dimensional vector of Float type.
- Vector2
- The Vector2 trait describes a 3-dimensional vector of Float
- Vector3
- The Vector3 trait describes a 3-dimensional vector of Float
- Vector4
- The Vector4 trait describes a 3-dimensional vector of Float
- Vector3D
- This is probably a temporary trait used until SIMD supports Geometry3D and Geometry2D