Expand description
§Geometry library
This library provides for N-dimensional geometrical objects, particularly Vectors, Matrix, Quaternion operations.
The underlying type is [Num; N], so the data may be shared simply with other libraries, including OpenGL.
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.
The library operates on arrays of elements that support the
Num
trait, which requires basic arithmetic operations, copy,
clone, debug and display; some functions further require the
Float
trait, which also requires operations such as sqrt,
sin/cos, etc.
§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>()
.
§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 have associated 3-element and 4-element vectors types that must provide the Vector trait.
Types that provide Quaternion can be manipulated with negation, addition, subtraction, and multiplicaton, 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 provide AsRef for float arrays of length 4 and slices for fast import and export from memory structures. Currently 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 Vector<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-elemet 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, Point3D, Point4D>;
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::unit().rotate_x(90.0_f64.to_radians());
assert!(z.distance(&qx.apply3(&y)) < 1.0E-8);
assert!(y.distance(&qx.apply3(&-z)) < 1.0E-8);
assert!(x.distance(&qx.apply3(&x)) < 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::unit().rotate_y(90.0_f64.to_radians());
assert!(x.distance(&qy.apply3(&z)) < 1.0E-8);
assert!(z.distance(&qy.apply3(&-x)) < 1.0E-8);
assert!(y.distance(&qy.apply3(&y)) < 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(&qxy.apply3(&x)) < 1.0E-8);
assert!(z.distance(&qxy.apply3(&y)) < 1.0E-8);
assert!(x.distance(&qxy.apply3(&z)) < 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);
!
Modules§
- The glsl module is a place-holder for types that are compatible with GLSL
- Matrix library
- Quaternion module
- Vector functions module
Structs§
- A transformation that is a translation . scaling . rotation (i.e. it applies the rotation to an object, then scales it, then translates it)
Traits§
- The Float trait is required for matrix or vector elements which have a float aspect, such as
sqrt
. - This is an experimental trait - it bundles together a Vec2 and a Mat2.
- The Geometry3D trait supplies a framework for implementing 3D vector and matrix operations, and should also include the quaternion type.
- 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
- The Quaternion trait describes a 4-dimensional vector of Float type.
- The Transform trait describes a translation, rotation and scaling for 3D, represented eventually as a Mat4
- This is probably a temporary trait used until SIMD supports Geometry3D and Geometry2D