Skip to content

Commit

Permalink
Doc + slerp + conversions.
Browse files Browse the repository at this point in the history
  • Loading branch information
sebcrozet committed Feb 12, 2017
1 parent 377f8b5 commit 086e6e7
Show file tree
Hide file tree
Showing 66 changed files with 2,073 additions and 334 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ path = "src/lib.rs"
arbitrary = [ "quickcheck" ]

[dependencies]
rustc-serialize = "0.3"
typenum = "1.4"
generic-array = "0.2"
rand = "0.3"
num-traits = "0.1"
num-complex = "0.1"
approx = "0.1"
alga = "0.4"
serde = "0.9"
serde_derive = "0.9"
# clippy = "*"

[dependencies.quickcheck]
optional = true
version = "0.3"

[dev-dependencies]
serde_json = "0.9"
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
all:
cargo build --features "arbitrary"
CARGO_INCREMENTAL=1 cargo build --features "arbitrary"

doc:
cargo doc
CARGO_INCREMENTAL=1 cargo doc

bench:
cargo bench

test:
cargo test --features "arbitrary"
CARGO_INCREMENTAL=1 cargo test --features "arbitrary"
74 changes: 4 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<p align="center">
<img src="http://nalgebra.org/img/logo_nalgebra.svg" alt="crates.io">
</p>
<p align="center">
<a href="https://crates.io/crates/nalgebra">
<img src="http://meritbadge.herokuapp.com/nalgebra?style=flat-square" alt="crates.io">
Expand All @@ -8,75 +11,6 @@
</p>
<p align = "center">
<strong>
<a href="http://nalgebra.org/doc/nalgebra">Documentation</a> | <a href="http://users.nphysics.org">Forum</a>
<a href="http://nalgebra.org">Users guide</a> | <a href="http://nalgebra.org/rustdoc/nalgebra/index.html">Documentation</a> | <a href="http://users.nphysics.org">Forum</a>
</strong>
</p>

nalgebra
========

**nalgebra** is a low-dimensional linear algebra library written for Rust targeting:

* General-purpose linear algebra (still lacks a lot of features…)
* Real time computer graphics.
* Real time computer physics.

## Using **nalgebra**
You will need the last stable build of the [rust compiler](http://www.rust-lang.org)
and the official package manager: [cargo](https://github.com/rust-lang/cargo).

Simply add the following to your `Cargo.toml` file:

```.ignore
[dependencies]
nalgebra = "0.10.*"
```


All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`. This
module re-exports everything and includes free functions for all traits methods performing
out-of-place operations.

Thus, you can import the whole prelude using:

```.ignore
use nalgebra::*;
```

However, the recommended way to use **nalgebra** is to import types and traits
explicitly, and call free-functions using the `na::` prefix:

```.rust
extern crate nalgebra as na;
use na::{Vector3, Rotation3, Rotation};
fn main() {
let a = Vector3::new(1.0f64, 1.0, 1.0);
let mut b = Rotation3::new(na::zero());
b.append_rotation_mut(&a);
assert!(na::approx_eq(&na::rotation(&b), &a));
}
```


## Features
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
an optimized set of tools for computer graphics and physics. Those features include:

* Vectors with predefined static sizes: `Vector1`, `Vector2`, `Vector3`, `Vector4`, `Vector5`, `Vector6`.
* Vector with a user-defined static size: `VectorN` (available only with the `generic_sizes` feature).
* Points with static sizes: `Point1`, `Point2`, `Point3`, `Point4`, `Point5`, `Point6`.
* Square matrices with static sizes: `Matrix1`, `Matrix2`, `Matrix3`, `Matrix4`, `Matrix5`, `Matrix6 `.
* Rotation matrices: `Rotation2`, `Rotation3`
* Quaternions: `Quaternion`, `Unit<Quaternion>`.
* Unit-sized values (unit vectors, unit quaternions, etc.): `Unit<T>`, e.g., `Unit<Vector3<f32>>`.
* Isometries (translation ⨯ rotation): `Isometry2`, `Isometry3`
* Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Similarity2`, `Similarity3`.
* 3D projections for computer graphics: `Persp3`, `PerspMatrix3`, `Ortho3`, `OrthoMatrix3`.
* Dynamically sized heap-allocated vector: `DVector`.
* Dynamically sized stack-allocated vectors with a maximum size: `DVector1` to `DVector6`.
* Dynamically sized heap-allocated (square or rectangular) matrix: `DMatrix`.
* Linear algebra and data analysis operators: `Covariance`, `Mean`, `qr`, `cholesky`.
* Almost one trait per functionality: useful for generic programming.
66 changes: 66 additions & 0 deletions examples/dimensional_genericity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
extern crate alga;
extern crate nalgebra as na;

use alga::general::Real;
use alga::linear::FiniteDimInnerSpace;
use na::{Unit, ColumnVector, OwnedColumnVector, Vector2, Vector3};
use na::storage::Storage;
use na::dimension::{DimName, U1};

/// Reflects a vector wrt. the hyperplane with normal `plane_normal`.
fn reflect_wrt_hyperplane_with_algebraic_genericity<V>(plane_normal: &Unit<V>, vector: &V) -> V
where V: FiniteDimInnerSpace + Copy {
let n = plane_normal.as_ref(); // Get the underlying vector of type `V`.
*vector - *n * (n.dot(vector) * na::convert(2.0))
}


/// Reflects a vector wrt. the hyperplane with normal `plane_normal`.
fn reflect_wrt_hyperplane_with_structural_genericity<N, D, S>(plane_normal: &Unit<ColumnVector<N, D, S>>,
vector: &ColumnVector<N, D, S>)
-> OwnedColumnVector<N, D, S::Alloc>
where N: Real,
D: DimName,
S: Storage<N, D, U1> {
let n = plane_normal.as_ref(); // Get the underlying V.
vector - n * (n.dot(vector) * na::convert(2.0))
}

/// Reflects a 2D vector wrt. the 2D line with normal `plane_normal`.
fn reflect_wrt_hyperplane2<N>(plane_normal: &Unit<Vector2<N>>,
vector: &Vector2<N>)
-> Vector2<N>
where N: Real {
let n = plane_normal.as_ref(); // Get the underlying Vector2
vector - n * (n.dot(vector) * na::convert(2.0))
}

/// Reflects a 3D vector wrt. the 3D plane with normal `plane_normal`.
/// /!\ This is an exact replicate of `reflect_wrt_hyperplane2, but for 3D.
fn reflect_wrt_hyperplane3<N>(plane_normal: &Unit<Vector3<N>>,
vector: &Vector3<N>)
-> Vector3<N>
where N: Real {
let n = plane_normal.as_ref(); // Get the underlying Vector3
vector - n * (n.dot(vector) * na::convert(2.0))
}


fn main() {
let plane2 = Vector2::y_axis(); // 2D plane normal.
let plane3 = Vector3::y_axis(); // 3D plane normal.

let v2 = Vector2::new(1.0, 2.0); // 2D vector to be reflected.
let v3 = Vector3::new(1.0, 2.0, 3.0); // 3D vector to be reflected.

// We can call the same function for 2D and 3D.
assert_eq!(reflect_wrt_hyperplane_with_algebraic_genericity(&plane2, &v2).y, -2.0);
assert_eq!(reflect_wrt_hyperplane_with_algebraic_genericity(&plane3, &v3).y, -2.0);

assert_eq!(reflect_wrt_hyperplane_with_structural_genericity(&plane2, &v2).y, -2.0);
assert_eq!(reflect_wrt_hyperplane_with_structural_genericity(&plane3, &v3).y, -2.0);

// Call each specific implementation depending on the dimension.
assert_eq!(reflect_wrt_hyperplane2(&plane2, &v2).y, -2.0);
assert_eq!(reflect_wrt_hyperplane3(&plane3, &v3).y, -2.0);
}
45 changes: 45 additions & 0 deletions examples/homogeneous_coordinates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#[macro_use]
extern crate approx;
extern crate nalgebra as na;

use std::f32;
use na::{Vector2, Point2, Isometry2};


fn use_dedicated_types() {
let iso = Isometry2::new(Vector2::new(1.0, 1.0), f32::consts::PI);
let pt = Point2::new(1.0, 0.0);
let vec = Vector2::x();

let transformed_pt = iso * pt;
let transformed_vec = iso * vec;

assert_relative_eq!(transformed_pt, Point2::new(0.0, 1.0));
assert_relative_eq!(transformed_vec, Vector2::new(-1.0, 0.0));
}

fn use_homogeneous_coordinates() {
let iso = Isometry2::new(Vector2::new(1.0, 1.0), f32::consts::PI);
let pt = Point2::new(1.0, 0.0);
let vec = Vector2::x();

// Compute using homogeneous coordinates.
let hom_iso = iso.to_homogeneous();
let hom_pt = pt.to_homogeneous();
let hom_vec = vec.to_homogeneous();

let hom_transformed_pt = hom_iso * hom_pt;
let hom_transformed_vec = hom_iso * hom_vec;

// Convert back to the cartesian coordinates.
let transformed_pt = Point2::from_homogeneous(hom_transformed_pt).unwrap();
let transformed_vec = Vector2::from_homogeneous(hom_transformed_vec).unwrap();

assert_relative_eq!(transformed_pt, Point2::new(0.0, 1.0));
assert_relative_eq!(transformed_vec, Vector2::new(-1.0, 0.0));
}

fn main() {
use_dedicated_types();
use_homogeneous_coordinates();
}
42 changes: 42 additions & 0 deletions examples/identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
extern crate alga;
extern crate nalgebra as na;


use alga::linear::Transformation;
use na::{Id, Vector3, Point3, Isometry3};

/*
* Applies `n` times the transformation `t` to the vector `v` and sum each
* intermediate value.
*/
fn complicated_algorithm<T>(v: &Vector3<f32>, t: &T, n: usize) -> Vector3<f32>
where T: Transformation<Point3<f32>> {

let mut result = *v;

// Do lots of operations involving t.
for _ in 0 .. n {
result = v + t.transform_vector(&result);
}

result
}


/*
* The two following calls are equivalent in term of result.
*/
fn main() {
let v = Vector3::new(1.0, 2.0, 3.0);

// The specialization generated by the compiler will do vector additions only.
let result1 = complicated_algorithm(&v, &Id::new(), 100000);

// The specialization generated by the compiler will also include matrix multiplications.
let iso = Isometry3::identity();
let result2 = complicated_algorithm(&v, &iso, 100000);

// They both return the same result.
assert!(result1 == Vector3::new(100001.0, 200002.0, 300003.0));
assert!(result2 == Vector3::new(100001.0, 200002.0, 300003.0));
}
62 changes: 62 additions & 0 deletions examples/matrix_construction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
extern crate nalgebra as na;

use na::{Vector2, RowVector3, Matrix2x3, DMatrix};


fn main() {
// All the following matrices are equal but constructed in different ways.
let m = Matrix2x3::new(1.1, 1.2, 1.3,
2.1, 2.2, 2.3);

let m1 = Matrix2x3::from_rows(&[
RowVector3::new(1.1, 1.2, 1.3),
RowVector3::new(2.1, 2.2, 2.3)
]);

let m2 = Matrix2x3::from_columns(&[
Vector2::new(1.1, 2.1),
Vector2::new(1.2, 2.2),
Vector2::new(1.3, 2.3)
]);

let m3 = Matrix2x3::from_row_slice(&[
1.1, 1.2, 1.3,
2.1, 2.2, 2.3
]);

let m4 = Matrix2x3::from_column_slice(&[
1.1, 2.1,
1.2, 2.2,
1.3, 2.3
]);

let m5 = Matrix2x3::from_fn(|r, c| (r + 1) as f32 + (c + 1) as f32 / 10.0);

let m6 = Matrix2x3::from_iterator([ 1.1f32, 2.1, 1.2, 2.2, 1.3, 2.3 ].iter().cloned());

assert_eq!(m, m1); assert_eq!(m, m2); assert_eq!(m, m3);
assert_eq!(m, m4); assert_eq!(m, m5); assert_eq!(m, m6);

// All the following matrices are equal but constructed in different ways.
// This time, we used a dynamically-sized matrix to show the extra arguments
// for the matrix shape.
let dm = DMatrix::from_row_slice(4, 3, &[
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 0.0
]);

let dm1 = DMatrix::from_diagonal_element(4, 3, 1.0);
let dm2 = DMatrix::identity(4, 3);
let dm3 = DMatrix::from_fn(4, 3, |r, c| if r == c { 1.0 } else { 0.0 });
let dm4 = DMatrix::from_iterator(4, 3, [
// Components listed column-by-column.
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
].iter().cloned());

assert_eq!(dm, dm1); assert_eq!(dm, dm2);
assert_eq!(dm, dm3); assert_eq!(dm, dm4);
}
28 changes: 28 additions & 0 deletions examples/mvp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![allow(unused_variables)]

extern crate nalgebra as na;

use na::{Vector3, Point3, Isometry3, Perspective3};

fn main() {
// Our object is translated along the x axis.
let model = Isometry3::new(Vector3::x(), na::zero());

// Our camera looks toward the point (1.0, 0.0, 0.0).
// It is located at (0.0, 0.0, 1.0).
let eye = Point3::new(0.0, 0.0, 1.0);
let target = Point3::new(1.0, 0.0, 0.0);
let view = Isometry3::look_at_rh(&eye, &target, &Vector3::y());

// A perspective projection.
let projection = Perspective3::new(16.0 / 9.0, 3.14 / 2.0, 1.0, 1000.0);

// The combination of the model with the view is still an isometry.
let model_view = model * view;

// Convert everything to a `Matrix4` so that they can be combined.
let mat_model_view = model_view.to_homogeneous();

// Combine everything.
let model_view_projection = projection.as_matrix() * mat_model_view;
}
Loading

0 comments on commit 086e6e7

Please sign in to comment.