Crate geo_nd

source ·
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

The FArray is a wrapper around a D sized array of Floats.
The FArray2 is a wrapper around a D2 = D^2` sized array of Floats.
A transformation that is a translation . scaling . rotation (i.e. it applies the rotation to an object, then scales it, then translates it)
The QArray is a wrapper around a D sized array of Floats.

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 SqMatrix trait describes an N-dimensional square matrix of Float type that operates on a Vector.
The SqMatrix3 trait describes a 3-dimensional square matrix of Float type that operates on a Vector.
The SqMatrix4 trait describes a 4-dimensional square matrix of Float type that operates on a Vector.
The Transform trait describes a translation, rotation and scaling for 3D, represented eventually as a Mat4
The Vector trait describes an N-dimensional vector of Float type.
The Vector3 trait describes a 3-dimensional vector of Float
This is probably a temporary trait used until SIMD supports Geometry3D and Geometry2D