forked from M-Labs/nalgebra
Huge api change!
Everything changed, hopefully for the best. * everything is accessible from the `na` module. It re-export everything and provides free functions (i-e: na::dot(a, b) instead of a.dot(b)) for most functionalities. * matrix/vector adaptors (Rotmat, Transform) are replaced by plain types: Rot{2, 3, 4} for rotation matrices and Iso{2, 3, 4} for isometries (rotation + translation). This old adaptors system was to hard to understand and to document. * each file related to data structures moved to the `structs` folder. This makes the doc a lot more readable and make people prefer the `na` module instead of individual small modules. * Because `na` exists now, the modules `structs::vec` and `structs::mat` dont re-export anything now. As a side effect, this makes the documentation more readable.
This commit is contained in:
parent
2356723e90
commit
84212f1449
88
README.md
88
README.md
@ -1,8 +1,36 @@
|
||||
nalgebra
|
||||
========
|
||||
# nalgebra
|
||||
|
||||
**nalgebra** is a _n_-dimensional linear algebra library written with the rust
|
||||
programming language.
|
||||
**nalgebra** is a linear algebra library written for Rust targeting:
|
||||
|
||||
* general-purpose linear algebra (still misses a lot of features…).
|
||||
* real time computer graphics.
|
||||
* real time computer physics.
|
||||
|
||||
## Using nalgebra
|
||||
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
|
||||
This module re-exports everything and includes free functions for all traits methods.
|
||||
Free functions are useful if you prefer doing something like: `na::dot(v1, v2)` instead of
|
||||
`v1.dot(v2)`.
|
||||
|
||||
* You can import the whole prelude, including free functions, using:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::na::*;
|
||||
```
|
||||
|
||||
* If you dont want to import everything but only every trait:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::traits::*;
|
||||
```
|
||||
|
||||
* If you dont want to import everything but only every structure:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::structs::*;
|
||||
```
|
||||
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
|
||||
prefix.
|
||||
|
||||
## Features
|
||||
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
|
||||
@ -10,25 +38,30 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
|
||||
|
||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
|
||||
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
|
||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
||||
* Dynamically sized vector: `DVec`.
|
||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
||||
* Geometry-specific matrix wrapper to ensure at compile-time some properties: `Rotmat`, `Transform`.
|
||||
* Most well-known geometric functions.
|
||||
* A few methods for data analysis: `Cov` (covariance), `Mean` (mean).
|
||||
* Operator overloading using the double trait dispatch [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
|
||||
This allows using operators for both matrix/matrix multiplication and matrix/vector
|
||||
multiplication for example.
|
||||
* Almost one trait per functionality. This is very useful for generic programming.
|
||||
|
||||
Since there is almost one trait per functionality, one might end up importing a lot of traits. To
|
||||
lighten your `use` prelude, all trait are re-exported by the `nalgebra::vec` and `nalgebra::mat`
|
||||
modules. Thus, to bring every functionalities of `nalgebra` in scope, you can do:
|
||||
* A few methods for data analysis: `Cov`, `Mean`.
|
||||
* Operator overloading using the double trait dispatch [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/). For example, the following work:
|
||||
|
||||
```rust
|
||||
use nalgebra::vec::*;
|
||||
use nalgebra::mat::*;
|
||||
extern mod nalgebra;
|
||||
use nalgebra::na::{Vec3, Mat3};
|
||||
|
||||
fn main() {
|
||||
let v: Vec3<f64> = Zero::zero();
|
||||
let m: Mat3<f64> = One::one();
|
||||
|
||||
let _ = m * v; // matrix-vector multiplication.
|
||||
let _ = v * m; // vector-matrix multiplication.
|
||||
let _ = m * m; // matrix-matrix multiplication.
|
||||
let _ = v * 2.0; // vector-scalar multiplication.
|
||||
}
|
||||
```
|
||||
|
||||
* Almost one trait per functionality: useful for generic programming.
|
||||
|
||||
## Compilation
|
||||
You will need the last rust compiler from the master branch.
|
||||
If you encounter problems, make sure you have the last version before creating an issue.
|
||||
@ -37,21 +70,8 @@ If you encounter problems, make sure you have the last version before creating a
|
||||
cd nalgebra
|
||||
make
|
||||
|
||||
There is also a light, but existing, documentation for most functionalities. Use `make doc` to
|
||||
generate it on the `doc` folder.
|
||||
You can build the documentation on the `doc` folder using:
|
||||
|
||||
## nalgebra in use
|
||||
Feel free to add your project to this list if you happen to use **nalgebra**!
|
||||
|
||||
* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
|
||||
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
|
||||
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
|
||||
* [frog](https://github.com/natal/frog): a machine learning library.
|
||||
|
||||
## Design note
|
||||
|
||||
**nalgebra** is mostly written with non-idiomatic rust code. This is mostly because of limitations
|
||||
of the trait system not allowing (easy) multiple overloading. Those overloading problems ares
|
||||
worked around by this
|
||||
[hack](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/)
|
||||
(section _What if I want overloading_).
|
||||
```.rust
|
||||
make doc
|
||||
```
|
||||
|
@ -1,478 +0,0 @@
|
||||
use std::num::{One, Zero};
|
||||
use std::rand::{Rand, Rng};
|
||||
use std::cmp::ApproxEq;
|
||||
use traits::geometry::{Cross, Rotation, Rotate, RotationMatrix, AbsoluteRotate, Transform,
|
||||
ToHomogeneous, Norm};
|
||||
use traits::structure::{Dim, Row, Col, Indexable};
|
||||
use traits::operations::{Inv, Transpose, Absolute};
|
||||
use vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
|
||||
use mat::{Mat2, Mat3, Mat4};
|
||||
|
||||
#[path = "../metal.rs"]
|
||||
mod metal;
|
||||
|
||||
/// Matrix wrapper representing rotation matrix.
|
||||
///
|
||||
/// It is built uppon another matrix and ensures (at the type-level) that it will always represent
|
||||
/// a rotation. Rotation matrices have some properties useful for performances, like the fact that
|
||||
/// the inversion is simply a transposition.
|
||||
#[deriving(Eq, ToStr, Clone)]
|
||||
pub struct Rotmat<M> {
|
||||
priv submat: M
|
||||
}
|
||||
|
||||
/// Trait of object `o` which can be multiplied by a `Rotmat` `r`: `r * o`.
|
||||
pub trait RotmatMulRhs<M, Res> {
|
||||
/// Multiplies a rotation matrix by `Self`.
|
||||
fn binop(left: &Rotmat<M>, right: &Self) -> Res;
|
||||
}
|
||||
|
||||
impl<M, Rhs: RotmatMulRhs<M, Res>, Res> Mul<Rhs, Res> for Rotmat<M> {
|
||||
#[inline(always)]
|
||||
fn mul(&self, other: &Rhs) -> Res {
|
||||
RotmatMulRhs::binop(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Clone> Rotmat<M> {
|
||||
/// Gets a copy of the internal representation of the rotation.
|
||||
pub fn submat(&self) -> M {
|
||||
self.submat.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>> {
|
||||
/// Builds a 2 dimensional rotation matrix from an angle in radian.
|
||||
pub fn from_angle(angle: N) -> Rotmat<Mat2<N>> {
|
||||
let (sia, coa) = angle.sin_cos();
|
||||
|
||||
Rotmat {
|
||||
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Trigonometric + Num + Algebraic> Rotmat<Mat3<N>> {
|
||||
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
|
||||
/// in radian. Its direction is the axis of rotation.
|
||||
pub fn from_axis_angle(axisangle: Vec3<N>) -> Rotmat<Mat3<N>> {
|
||||
if axisangle.sqnorm().is_zero() {
|
||||
One::one()
|
||||
}
|
||||
else {
|
||||
let mut axis = axisangle;
|
||||
let angle = axis.normalize();
|
||||
let _1: N = One::one();
|
||||
let ux = axis.x.clone();
|
||||
let uy = axis.y.clone();
|
||||
let uz = axis.z.clone();
|
||||
let sqx = ux * ux;
|
||||
let sqy = uy * uy;
|
||||
let sqz = uz * uz;
|
||||
let (sin, cos) = angle.sin_cos();
|
||||
let one_m_cos = _1 - cos;
|
||||
|
||||
Rotmat {
|
||||
submat: Mat3::new(
|
||||
(sqx + (_1 - sqx) * cos),
|
||||
(ux * uy * one_m_cos - uz * sin),
|
||||
(ux * uz * one_m_cos + uy * sin),
|
||||
|
||||
(ux * uy * one_m_cos + uz * sin),
|
||||
(sqy + (_1 - sqy) * cos),
|
||||
(uy * uz * one_m_cos - ux * sin),
|
||||
|
||||
(ux * uz * one_m_cos - uy * sin),
|
||||
(uy * uz * one_m_cos + ux * sin),
|
||||
(sqz + (_1 - sqz) * cos))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Num + Algebraic> Rotmat<Mat3<N>> {
|
||||
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
|
||||
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
|
||||
/// for that.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
|
||||
/// with
|
||||
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
let xaxis = at.normalized();
|
||||
let zaxis = up.cross(&xaxis).normalized();
|
||||
let yaxis = zaxis.cross(&xaxis);
|
||||
|
||||
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
|
||||
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
|
||||
xaxis.z , yaxis.z , zaxis.z)
|
||||
}
|
||||
|
||||
/// Reorient this matrix such that its local `z` axis points to a given point.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
|
||||
/// with
|
||||
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
let zaxis = at.normalized();
|
||||
let xaxis = up.cross(&zaxis).normalized();
|
||||
let yaxis = zaxis.cross(&xaxis);
|
||||
|
||||
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
|
||||
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
|
||||
xaxis.z , yaxis.z , zaxis.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Trigonometric + Num + Clone>
|
||||
RotationMatrix<Vec2<N>, Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> Rotmat<Mat2<N>> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Trigonometric + Num + Clone>
|
||||
Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec1<N> {
|
||||
Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec1<N> {
|
||||
-self.rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &Vec1<N>) {
|
||||
*self = self.rotated(rot)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>> {
|
||||
Rotmat::from_angle(rot.x.clone()) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rot: Vec1<N>) {
|
||||
*self = Rotmat::from_angle(rot.x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
|
||||
RotationMatrix<Vec3<N>, Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> Rotmat<Mat3<N>> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
|
||||
Rotation<Vec3<N>> for Rotmat<Mat3<N>> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec3<N> {
|
||||
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / NumCast::from(2.0)).acos();
|
||||
|
||||
if angle != angle {
|
||||
// FIXME: handle that correctly
|
||||
Zero::zero()
|
||||
}
|
||||
else if angle.is_zero() {
|
||||
Zero::zero()
|
||||
}
|
||||
else {
|
||||
let m32_m23 = self.submat.m32 - self.submat.m23;
|
||||
let m13_m31 = self.submat.m13 - self.submat.m31;
|
||||
let m21_m12 = self.submat.m21 - self.submat.m12;
|
||||
|
||||
let denom = (m32_m23 * m32_m23 + m13_m31 * m13_m31 + m21_m12 * m21_m12).sqrt();
|
||||
|
||||
if denom.is_zero() {
|
||||
// XXX: handle that properly
|
||||
// fail!("Internal error: singularity.")
|
||||
Zero::zero()
|
||||
}
|
||||
else {
|
||||
let a_d = angle / denom;
|
||||
|
||||
Vec3::new(m32_m23 * a_d, m13_m31 * a_d, m21_m12 * a_d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec3<N> {
|
||||
-self.rotation()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &Vec3<N>) {
|
||||
*self = self.rotated(rot)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>> {
|
||||
Rotmat::from_axis_angle(axisangle.clone()) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, axisangle: Vec3<N>) {
|
||||
*self = Rotmat::from_axis_angle(axisangle)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>> {
|
||||
Rotmat::from_angle(rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Rotate<V> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &V) -> V {
|
||||
self * *v
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotate(&self, v: &V) -> V {
|
||||
v * *self
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Transform<V> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &V) -> V {
|
||||
self.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, v: &V) -> V {
|
||||
self.inv_rotate(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
|
||||
Rand for Rotmat<Mat3<N>> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>> {
|
||||
Rotmat::from_axis_angle(rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Dim> Dim for Rotmat<M> {
|
||||
#[inline]
|
||||
fn dim(_: Option<Rotmat<M>>) -> uint {
|
||||
Dim::dim(None::<M>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: One + Zero> One for Rotmat<M> {
|
||||
#[inline]
|
||||
fn one() -> Rotmat<M> {
|
||||
Rotmat { submat: One::one() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Mul<M, M>> RotmatMulRhs<M, Rotmat<M>> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn binop(left: &Rotmat<M>, right: &Rotmat<M>) -> Rotmat<M> {
|
||||
Rotmat { submat: left.submat * right.submat }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Right/Left multiplication implementation for Vec3 and Vec2.
|
||||
*/
|
||||
impl<M: Mul<Vec4<N>, Vec4<N>>, N> RotmatMulRhs<M, Vec4<N>> for Vec4<N> {
|
||||
#[inline]
|
||||
fn binop(left: &Rotmat<M>, right: &Vec4<N>) -> Vec4<N> {
|
||||
left.submat * *right
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Mul<Vec3<N>, Vec3<N>>, N> RotmatMulRhs<M, Vec3<N>> for Vec3<N> {
|
||||
#[inline]
|
||||
fn binop(left: &Rotmat<M>, right: &Vec3<N>) -> Vec3<N> {
|
||||
left.submat * *right
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Mul<Vec2<N>, Vec2<N>>, N> RotmatMulRhs<M, Vec2<N>> for Vec2<N> {
|
||||
#[inline]
|
||||
fn binop(left: &Rotmat<M>, right: &Vec2<N>) -> Vec2<N> {
|
||||
left.submat * *right
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, M: Vec4MulRhs<N, Vec4<N>>> Vec4MulRhs<N, Vec4<N>> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn binop(left: &Vec4<N>, right: &Rotmat<M>) -> Vec4<N> {
|
||||
*left * right.submat
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, M: Vec3MulRhs<N, Vec3<N>>> Vec3MulRhs<N, Vec3<N>> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn binop(left: &Vec3<N>, right: &Rotmat<M>) -> Vec3<N> {
|
||||
*left * right.submat
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, M: Vec2MulRhs<N, Vec2<N>>> Vec2MulRhs<N, Vec2<N>> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn binop(left: &Vec2<N>, right: &Rotmat<M>) -> Vec2<N> {
|
||||
*left * right.submat
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Transpose> Inv for Rotmat<M> {
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
self.transpose();
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Rotmat<M>> {
|
||||
Some(self.transposed())
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Transpose>
|
||||
Transpose for Rotmat<M> {
|
||||
#[inline]
|
||||
fn transposed(&self) -> Rotmat<M> {
|
||||
Rotmat { submat: self.submat.transposed() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose(&mut self) {
|
||||
self.submat.transpose()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Row<R>, R> Row<R> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn num_rows(&self) -> uint {
|
||||
self.submat.num_rows()
|
||||
}
|
||||
#[inline]
|
||||
fn row(&self, i: uint) -> R {
|
||||
self.submat.row(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_row(&mut self, i: uint, row: R) {
|
||||
self.submat.set_row(i, row);
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Col<C>, C> Col<C> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn num_cols(&self) -> uint {
|
||||
self.submat.num_cols()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn col(&self, i: uint) -> C {
|
||||
self.submat.col(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_col(&mut self, i: uint, col: C) {
|
||||
self.submat.set_col(i, col);
|
||||
}
|
||||
}
|
||||
|
||||
// we loose the info that we are a rotation matrix
|
||||
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn to_homogeneous(&self) -> M2 {
|
||||
self.submat.to_homogeneous()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> N {
|
||||
// ApproxEq::<N>::approx_epsilon()
|
||||
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &Rotmat<M>) -> bool {
|
||||
self.submat.approx_eq(&other.submat)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool {
|
||||
self.submat.approx_eq_eps(&other.submat, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Absolute<M2>, M2> Absolute<M2> for Rotmat<M> {
|
||||
#[inline]
|
||||
fn absolute(&self) -> M2 {
|
||||
self.submat.absolute()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rotmat<Mat4<N>> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec4<N>) -> Vec4<N> {
|
||||
Vec4::new(
|
||||
self.submat.m11.abs() * v.x +
|
||||
self.submat.m12.abs() * v.y +
|
||||
self.submat.m13.abs() * v.z +
|
||||
self.submat.m14.abs() * v.w,
|
||||
|
||||
self.submat.m21.abs() * v.x +
|
||||
self.submat.m22.abs() * v.y +
|
||||
self.submat.m23.abs() * v.z +
|
||||
self.submat.m24.abs() * v.w,
|
||||
|
||||
self.submat.m31.abs() * v.x +
|
||||
self.submat.m32.abs() * v.y +
|
||||
self.submat.m33.abs() * v.z +
|
||||
self.submat.m34.abs() * v.w,
|
||||
|
||||
self.submat.m41.abs() * v.x +
|
||||
self.submat.m42.abs() * v.y +
|
||||
self.submat.m43.abs() * v.z +
|
||||
self.submat.m44.abs() * v.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rotmat<Mat3<N>> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec3<N>) -> Vec3<N> {
|
||||
Vec3::new(
|
||||
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z,
|
||||
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z,
|
||||
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rotmat<Mat2<N>> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec2<N>) -> Vec2<N> {
|
||||
// the matrix is skew-symetric, so we dont need to compute the absolute value of every
|
||||
// component.
|
||||
let m11 = self.submat.m11.abs();
|
||||
let m12 = self.submat.m12.abs();
|
||||
let m22 = self.submat.m22.abs();
|
||||
|
||||
Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y)
|
||||
}
|
||||
}
|
@ -1,394 +0,0 @@
|
||||
use std::num::{One, Zero};
|
||||
use std::rand::{Rand, Rng};
|
||||
use std::cmp::ApproxEq;
|
||||
use traits::structure::{Dim, Mat, Col};
|
||||
use traits::operations::{Absolute, Inv, RMul};
|
||||
use traits::geometry::{Rotation, Rotate, RotationMatrix, Translation, Translate, Transformation,
|
||||
ToHomogeneous, FromHomogeneous, AbsoluteRotate};
|
||||
use Ts = traits::geometry::Transform;
|
||||
use adaptors::rotmat::Rotmat;
|
||||
use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
|
||||
use mat::Mat3;
|
||||
|
||||
/// Matrix-Vector wrapper used to represent a matrix multiplication followed by a translation.
|
||||
///
|
||||
/// Usually, a matrix in homogeneous coordinate is used to be able to apply an affine transform with
|
||||
/// a translation to a vector. This is weird because it makes a `n`-dimentional transformation be
|
||||
/// an `n + 1`-matrix. Using the `Transform` wrapper avoid homogeneous coordinates by having the
|
||||
/// translation separate from the other transformations. This is particularity useful when the
|
||||
/// underlying transform is a rotation (see `Rotmat`): this makes inversion much faster than
|
||||
/// inverting the homogeneous matrix itself.
|
||||
#[deriving(Eq, ToStr, Clone)]
|
||||
pub struct Transform<V, M> {
|
||||
priv submat : M,
|
||||
priv subtrans : V
|
||||
}
|
||||
|
||||
// FIXME: this should be Trasform<V, M>
|
||||
impl<V, M> Transform<V, M> {
|
||||
/// Builds a new transform from a matrix and a vector.
|
||||
#[inline]
|
||||
pub fn new(trans: V, mat: M) -> Transform<V, M> {
|
||||
Transform {
|
||||
submat: mat,
|
||||
subtrans: trans
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait of object `o` which can be multiplied by a `Transform` `t`: `t * o`.
|
||||
pub trait TransformMulRhs<V, M, Res> {
|
||||
/// Multiplies a transformation matrix by `Self`.
|
||||
fn binop(left: &Transform<V, M>, right: &Self) -> Res;
|
||||
}
|
||||
|
||||
impl<V, M, Rhs: TransformMulRhs<V, M, Res>, Res> Mul<Rhs, Res> for Transform<V, M> {
|
||||
#[inline(always)]
|
||||
fn mul(&self, other: &Rhs) -> Res {
|
||||
TransformMulRhs::binop(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Clone, M: Clone> Transform<V, M> {
|
||||
/// Gets a copy of the internal matrix.
|
||||
#[inline]
|
||||
pub fn submat(&self) -> M {
|
||||
self.submat.clone()
|
||||
}
|
||||
|
||||
/// Gets a copy of the internal translation.
|
||||
#[inline]
|
||||
pub fn subtrans(&self) -> V {
|
||||
self.subtrans.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<LV, AV, M: One + RMul<LV> + RotationMatrix<LV, AV, M2>, M2: Mat<LV, LV> + Rotation<AV>>
|
||||
RotationMatrix<LV, AV, M2> for Transform<LV, M> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> M2 {
|
||||
self.submat.to_rot_mat()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Num + Algebraic> Transform<Vec3<N>, Rotmat<Mat3<N>>> {
|
||||
/// Reorient and translate this transformation such that its local `x` axis points to a given
|
||||
/// direction. Note that the usually known `look_at` function does the same thing but with the
|
||||
/// `z` axis. See `look_at_z` for that.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * eye - The new translation of the transformation.
|
||||
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
|
||||
/// aligned with.
|
||||
/// * up - Vector pointing up. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
self.submat.look_at(&(*at - *eye), up);
|
||||
self.subtrans = eye.clone();
|
||||
}
|
||||
|
||||
/// Reorient and translate this transformation such that its local `z` axis points to a given
|
||||
/// direction.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * eye - The new translation of the transformation.
|
||||
/// * at - The point to look at. `at - eye` is the direction the matrix `x` axis will be
|
||||
/// aligned with
|
||||
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at_z(&mut self, eye: &Vec3<N>, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
self.submat.look_at_z(&(*at - *eye), up);
|
||||
self.subtrans = eye.clone();
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Dim, V> Dim for Transform<V, M> {
|
||||
#[inline]
|
||||
fn dim(_: Option<Transform<V, M>>) -> uint {
|
||||
Dim::dim(None::<M>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: One, V: Zero> One for Transform<V, M> {
|
||||
#[inline]
|
||||
fn one() -> Transform<V, M> {
|
||||
Transform {
|
||||
submat: One::one(), subtrans: Zero::zero()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Zero, V: Zero> Zero for Transform<V, M> {
|
||||
#[inline]
|
||||
fn zero() -> Transform<V, M> {
|
||||
Transform {
|
||||
submat: Zero::zero(), subtrans: Zero::zero()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
self.submat.is_zero() && self.subtrans.is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>> TransformMulRhs<V, M, Transform<V, M>> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn binop(left: &Transform<V, M>, right: &Transform<V, M>) -> Transform<V, M> {
|
||||
Transform {
|
||||
submat: left.submat * right.submat,
|
||||
subtrans: left.subtrans + left.submat.rmul(&right.subtrans)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Add<N, N>, M: Mul<Vec2<N>, Vec2<N>>>
|
||||
TransformMulRhs<Vec2<N>, M, Vec2<N>> for Vec2<N> {
|
||||
#[inline]
|
||||
fn binop(left: &Transform<Vec2<N>, M>, right: &Vec2<N>) -> Vec2<N> {
|
||||
left.subtrans + left.submat * *right
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Add<N, N>, M: Mul<Vec3<N>, Vec3<N>>>
|
||||
TransformMulRhs<Vec3<N>, M, Vec3<N>> for Vec3<N> {
|
||||
#[inline]
|
||||
fn binop(left: &Transform<Vec3<N>, M>, right: &Vec3<N>) -> Vec3<N> {
|
||||
left.subtrans + left.submat * *right
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Add<N, N>, M: Vec2MulRhs<N, Vec2<N>>>
|
||||
Vec2MulRhs<N, Vec2<N>> for Transform<Vec2<N>, M> {
|
||||
#[inline]
|
||||
fn binop(left: &Vec2<N>, right: &Transform<Vec2<N>, M>) -> Vec2<N> {
|
||||
(left + right.subtrans) * right.submat
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Add<N, N>, M: Vec3MulRhs<N, Vec3<N>>>
|
||||
Vec3MulRhs<N, Vec3<N>> for Transform<Vec3<N>, M> {
|
||||
#[inline]
|
||||
fn binop(left: &Vec3<N>, right: &Transform<Vec3<N>, M>) -> Vec3<N> {
|
||||
(left + right.subtrans) * right.submat
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Clone, V: Translation<V>> Translation<V> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn translation(&self) -> V {
|
||||
self.subtrans.translation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_translation(&self) -> V {
|
||||
self.subtrans.inv_translation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn translate_by(&mut self, t: &V) {
|
||||
self.subtrans.translate_by(t)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn translated(&self, t: &V) -> Transform<V, M> {
|
||||
Transform::new(self.subtrans.translated(t), self.submat.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_translation(&mut self, t: V) {
|
||||
self.subtrans.set_translation(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, M: Translate<V>, _0> Translate<V> for Transform<_0, M> {
|
||||
#[inline]
|
||||
fn translate(&self, v: &V) -> V {
|
||||
self.submat.translate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_translate(&self, v: &V) -> V {
|
||||
self.submat.inv_translate(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Rotation<AV> + RMul<V> + One, V, AV>
|
||||
Rotation<AV> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> AV {
|
||||
self.submat.rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> AV {
|
||||
self.submat.inv_rotation()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &AV) {
|
||||
// FIXME: this does not seem opitmal
|
||||
let mut delta: M = One::one();
|
||||
delta.rotate_by(rot);
|
||||
self.submat.rotate_by(rot);
|
||||
self.subtrans = delta.rmul(&self.subtrans);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, rot: &AV) -> Transform<V, M> {
|
||||
// FIXME: this does not seem opitmal
|
||||
let _1: M = One::one();
|
||||
let delta = _1.rotated(rot);
|
||||
|
||||
Transform::new(delta.rmul(&self.subtrans), self.submat.rotated(rot))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rot: AV) {
|
||||
// FIXME: should the translation be changed too?
|
||||
self.submat.set_rotation(rot)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, M: Rotate<V>, _0> Rotate<V> for Transform<_0, M> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &V) -> V {
|
||||
self.submat.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotate(&self, v: &V) -> V {
|
||||
self.submat.inv_rotate(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Inv + RMul<V> + Mul<M, M> + Clone, V: Add<V, V> + Neg<V> + Clone>
|
||||
Transformation<Transform<V, M>> for Transform<V, M> {
|
||||
fn transformation(&self) -> Transform<V, M> {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
fn inv_transformation(&self) -> Transform<V, M> {
|
||||
// FIXME: fail or return a Some<Transform<V, M>> ?
|
||||
match self.inverse() {
|
||||
Some(t) => t,
|
||||
None => fail!("This transformation was not inversible.")
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_by(&mut self, other: &Transform<V, M>) {
|
||||
*self = other * *self
|
||||
}
|
||||
|
||||
fn transformed(&self, t: &Transform<V, M>) -> Transform<V, M> {
|
||||
t * *self
|
||||
}
|
||||
|
||||
fn set_transformation(&mut self, t: Transform<V, M>) {
|
||||
*self = t
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Ts<V>, V: Add<V, V> + Sub<V, V>>
|
||||
Ts<V> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &V) -> V {
|
||||
self.submat.transform(v) + self.subtrans
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, v: &V) -> V {
|
||||
self.submat.inv_transform(&(v - self.subtrans))
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Inv + RMul<V> + Clone, V: Neg<V> + Clone>
|
||||
Inv for Transform<V, M> {
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
if !self.submat.inplace_inverse() {
|
||||
false
|
||||
}
|
||||
else {
|
||||
self.subtrans = self.submat.rmul(&-self.subtrans);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Transform<V, M>> {
|
||||
let mut res = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: ToHomogeneous<M2>, M2: Dim + Col<V2>, V: ToHomogeneous<V2> + Clone, V2>
|
||||
ToHomogeneous<M2> for Transform<V, M> {
|
||||
fn to_homogeneous(&self) -> M2 {
|
||||
let mut res = self.submat.to_homogeneous();
|
||||
|
||||
// copy the translation
|
||||
let dim = Dim::dim(None::<M2>);
|
||||
|
||||
res.set_col(dim - 1, self.subtrans.to_homogeneous());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Col<V> + Dim, M2: FromHomogeneous<M>, V>
|
||||
FromHomogeneous<M> for Transform<V, M2> {
|
||||
fn from(m: &M) -> Transform<V, M2> {
|
||||
Transform::new(m.col(Dim::dim(None::<M>) - 1), FromHomogeneous::from(m))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N>, M:ApproxEq<N>, V:ApproxEq<N>>
|
||||
ApproxEq<N> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> N {
|
||||
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
|
||||
// ApproxEq::<N>::approx_epsilon()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &Transform<V, M>) -> bool {
|
||||
self.submat.approx_eq(&other.submat) &&
|
||||
self.subtrans.approx_eq(&other.subtrans)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &Transform<V, M>, epsilon: &N) -> bool {
|
||||
self.submat.approx_eq_eps(&other.submat, epsilon) &&
|
||||
self.subtrans.approx_eq_eps(&other.subtrans, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Rand, V: Rand> Rand for Transform<V, M> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Transform<V, M> {
|
||||
Transform::new(rng.gen(), rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Absolute<V2>, M: Absolute<M2>, V2, M2>
|
||||
Absolute<Transform<V2, M2>> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn absolute(&self) -> Transform<V2, M2> {
|
||||
Transform::new(self.subtrans.absolute(), self.submat.absolute())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, M: AbsoluteRotate<V>> AbsoluteRotate<V> for Transform<V, M> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &V) -> V {
|
||||
self.submat.absolute_rotate(v)
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
use std::rand::random;
|
||||
use extra::test::BenchHarness;
|
||||
use mat::*;
|
||||
use vec::*;
|
||||
use na::*;
|
||||
|
||||
macro_rules! bench_mul_mat(
|
||||
($bh: expr, $t: ty) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::rand::random;
|
||||
use extra::test::BenchHarness;
|
||||
use vec::*;
|
||||
use na::*;
|
||||
|
||||
macro_rules! bench_dot_vec(
|
||||
($bh: expr, $t: ty) => {
|
||||
|
118
src/lib.rs
118
src/lib.rs
@ -1,6 +1,92 @@
|
||||
/*!
|
||||
# nalgebra
|
||||
|
||||
# A n-dimensional linear algebra library.
|
||||
**nalgebra** is a linear algebra library written for Rust targeting:
|
||||
|
||||
* general-purpose linear algebra (still misses a lot of features…).
|
||||
* real time computer graphics.
|
||||
* real time computer physics.
|
||||
|
||||
## Using **nalgebra**
|
||||
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
|
||||
This module re-exports everything and includes free functions for all traits methods.
|
||||
Free functions are useful if you prefer doing something like: `na::dot(v1, v2)` instead of
|
||||
`v1.dot(v2)`.
|
||||
|
||||
* You can import the whole prelude, including free functions, using:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::na::*;
|
||||
```
|
||||
|
||||
* If you dont want to import everything but only every trait:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::traits::*;
|
||||
```
|
||||
|
||||
* If you dont want to import everything but only every structure:
|
||||
|
||||
```.rust
|
||||
pub use nalgebra::structs::*;
|
||||
```
|
||||
Of course, you can still import `nalgebra::na` alone, and get anything you want using the `na`
|
||||
prefix.
|
||||
|
||||
## Features
|
||||
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
|
||||
and keeps an optimized set of tools for computational graphics and physics. Those features include:
|
||||
|
||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, ..., `Vec6`.
|
||||
* Square matrices with static sizes: `Mat1`, `Mat2`, ..., `Mat6 `.
|
||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
||||
* Dynamically sized vector: `DVec`.
|
||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
||||
* A few methods for data analysis: `Cov`, `Mean`.
|
||||
* Operator overloading using the double trait dispatch
|
||||
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
|
||||
For example, the following work:
|
||||
|
||||
```rust
|
||||
extern mod nalgebra;
|
||||
use nalgebra::na::{Vec3, Mat3};
|
||||
|
||||
fn main() {
|
||||
let v: Vec3<f64> = Zero::zero();
|
||||
let m: Mat3<f64> = One::one();
|
||||
|
||||
let _ = m * v; // matrix-vector multiplication.
|
||||
let _ = v * m; // vector-matrix multiplication.
|
||||
let _ = m * m; // matrix-matrix multiplication.
|
||||
let _ = v * 2.0; // vector-scalar multiplication.
|
||||
}
|
||||
```
|
||||
|
||||
* Almost one trait per functionality: useful for generic programming.
|
||||
|
||||
## Compilation
|
||||
You will need the last rust compiler from the master branch.
|
||||
If you encounter problems, make sure you have the last version before creating an issue.
|
||||
|
||||
git clone git://github.com/sebcrozet/nalgebra.git
|
||||
cd nalgebra
|
||||
make
|
||||
|
||||
You can build the documentation on the `doc` folder using:
|
||||
|
||||
```.rust
|
||||
make doc
|
||||
```
|
||||
|
||||
## **nalgebra** in use
|
||||
Here are some projects using **nalgebra**.
|
||||
Feel free to add your project to this list if you happen to use **nalgebra**!
|
||||
|
||||
* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
|
||||
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
|
||||
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
|
||||
* [frog](https://github.com/natal/frog): a machine learning library.
|
||||
|
||||
*/
|
||||
#[link(name = "nalgebra"
|
||||
@ -16,34 +102,10 @@
|
||||
extern mod std;
|
||||
extern mod extra;
|
||||
|
||||
pub mod dmat;
|
||||
pub mod dvec;
|
||||
pub mod vec;
|
||||
pub mod mat;
|
||||
pub mod types;
|
||||
pub mod na;
|
||||
pub mod structs;
|
||||
pub mod traits;
|
||||
|
||||
/// Wrappers around raw matrices to restrict their behaviour.
|
||||
pub mod adaptors {
|
||||
pub mod rotmat;
|
||||
pub mod transform;
|
||||
}
|
||||
|
||||
/// Traits implemented by matrices and vectors. Re-exported by the `mat` or the `vec` module.
|
||||
pub mod traits {
|
||||
pub mod geometry;
|
||||
pub mod structure;
|
||||
pub mod operations;
|
||||
}
|
||||
|
||||
// specialization for some 1d, 2d and 3d operations
|
||||
#[doc(hidden)]
|
||||
mod spec {
|
||||
mod identity;
|
||||
mod mat;
|
||||
mod vec0;
|
||||
mod vec;
|
||||
// mod complex;
|
||||
}
|
||||
// mod lower_triangular;
|
||||
// mod chol;
|
||||
|
||||
|
549
src/na.rs
Normal file
549
src/na.rs
Normal file
@ -0,0 +1,549 @@
|
||||
//! **nalgebra** prelude.
|
||||
|
||||
pub use traits::{
|
||||
Absolute,
|
||||
AbsoluteRotate,
|
||||
AlgebraicVec,
|
||||
AlgebraicVecExt,
|
||||
Basis,
|
||||
Col,
|
||||
Cov,
|
||||
Cross,
|
||||
CrossMatrix,
|
||||
Dim,
|
||||
Dot,
|
||||
FromHomogeneous,
|
||||
Indexable,
|
||||
Inv,
|
||||
Iterable,
|
||||
IterableMut,
|
||||
LMul,
|
||||
Mat,
|
||||
MatCast,
|
||||
Mean,
|
||||
Norm,
|
||||
Outer,
|
||||
RMul,
|
||||
Rotate, Rotation, RotationMatrix, RotationWithTranslation,
|
||||
Row,
|
||||
ScalarAdd, ScalarSub,
|
||||
ToHomogeneous,
|
||||
Transform, Transformation,
|
||||
Translate, Translation,
|
||||
Transpose,
|
||||
UniformSphereSample,
|
||||
Vec,
|
||||
VecCast,
|
||||
VecExt
|
||||
};
|
||||
|
||||
pub use structs::{
|
||||
DMat, DVec,
|
||||
Iso2, Iso3, Iso4,
|
||||
Mat1, Mat2, Mat3, Mat4,
|
||||
Mat5, Mat6,
|
||||
Rot2, Rot3, Rot4,
|
||||
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
// Geometry
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
* Translation<V>
|
||||
*/
|
||||
|
||||
/// Gets the translation applicable by the given object.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern mod nalgebra;
|
||||
/// use nalgebra::types::{Vec3, Affmat};
|
||||
/// use nalgebra::na;
|
||||
///
|
||||
/// pub main() {
|
||||
/// let t = Affmat::new_translation3d(1.0, 1.0, 1.0);
|
||||
/// let trans = na::translation(t);
|
||||
///
|
||||
/// assert!(trans == Vec3::new(1.0, 1.0, 1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn translation<V, M: Translation<V>>(m: &M) -> V {
|
||||
m.translation()
|
||||
}
|
||||
|
||||
/// Gets the inverse translation applicable by the given object.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern mod nalgebra;
|
||||
/// use nalgebra::types::{Vec3, Affmat};
|
||||
/// use nalgebra::na;
|
||||
///
|
||||
/// pub main() {
|
||||
/// let t = Affmat::new_translation3d(1.0, 1.0, 1.0);
|
||||
/// let itrans = na::inv_translation(t);
|
||||
///
|
||||
/// assert!(itrans == Vec3::new(-1.0, -1.0, -1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn inv_translation<V, M: Translation<V>>(m: &M) -> V {
|
||||
m.inv_translation()
|
||||
}
|
||||
|
||||
/// In-place version of `translated`.
|
||||
#[inline(always)]
|
||||
pub fn translate_by<V, M: Translation<V>>(m: &mut M, v: &V) {
|
||||
m.translate_by(v)
|
||||
}
|
||||
|
||||
/// Gets a translated copy of the given object.
|
||||
#[inline(always)]
|
||||
pub fn translated<V, M: Translation<V>>(m: &M, v: &V) -> M {
|
||||
m.translated(v)
|
||||
}
|
||||
|
||||
/// Sets the translation of the given object.
|
||||
#[inline(always)]
|
||||
pub fn set_translation<V, M: Translation<V>>(m: &mut M, v: V) {
|
||||
m.set_translation(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
|
||||
m.translate(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn inv_translate<V, M: Translate<V>>(m: &M, v: &V) -> V {
|
||||
m.inv_translate(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotation<V>
|
||||
*/
|
||||
|
||||
/// Gets the rotation applicable by the given object.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern mod nalgebra;
|
||||
/// use nalgebra::na;
|
||||
///
|
||||
/// pub main() {
|
||||
/// let t = na::rotation3d(1.0, 1.0, 1.0);
|
||||
///
|
||||
/// assert!(na::rotation(t) == na::vec3(1.0, 1.0, 1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
m.rotation()
|
||||
}
|
||||
|
||||
|
||||
/// Gets the rotation applicable by the given object.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern mod nalgebra;
|
||||
/// use nalgebra::na;
|
||||
///
|
||||
/// pub main() {
|
||||
/// let t = na::rotation3d(1.0, 1.0, 1.0);
|
||||
///
|
||||
/// assert!(na::inv_rotation(t) == na::vec3(-1.0, -1.0, -1.0));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn inv_rotation<V, M: Rotation<V>>(m: &M) -> V {
|
||||
m.inv_rotation()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotate_by<V, M: Rotation<V>>(m: &mut M, v: &V) {
|
||||
m.rotate_by(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotated<V, M: Rotation<V>>(m: &M, v: &V) -> M {
|
||||
m.rotated(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn set_rotation<V, M: Rotation<V>>(m: &mut M, v: V) {
|
||||
m.set_rotation(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
m.rotate(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn inv_rotate<V, M: Rotate<V>>(m: &M, v: &V) -> V {
|
||||
m.inv_rotate(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* RotationWithTranslation<LV, AV>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotated_wrt_point<LV: Neg<LV>,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
m: &M,
|
||||
amount: &AV,
|
||||
center: &LV) -> M {
|
||||
m.rotated_wrt_point(amount, center)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotate_wrt_point<LV: Neg<LV>,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
m: &mut M,
|
||||
amount: &AV,
|
||||
center: &LV) {
|
||||
m.rotate_wrt_point(amount, center)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotated_wrt_center<LV: Neg<LV>,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
m: &M,
|
||||
amount: &AV) -> M {
|
||||
m.rotated_wrt_center(amount)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn rotate_wrt_center<LV: Neg<LV>,
|
||||
AV,
|
||||
M: RotationWithTranslation<LV, AV>>(
|
||||
m: &mut M,
|
||||
amount: &AV) {
|
||||
m.rotate_wrt_center(amount)
|
||||
}
|
||||
|
||||
/*
|
||||
* RotationMatrix<LV, AV, R>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn to_rot_mat<LV, AV, M: Mat<LV, LV> + Rotation<AV>, R: RotationMatrix<LV, AV, M>>(r: &R) -> M {
|
||||
r.to_rot_mat()
|
||||
}
|
||||
|
||||
/*
|
||||
* AbsoluteRotate<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn absolute_rotate<V, M: AbsoluteRotate<V>>(m: &M, v: &V) -> V {
|
||||
m.absolute_rotate(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Transformation<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transformation<V, M: Transformation<V>>(m: &M) -> V {
|
||||
m.transformation()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn inv_transformation<V, M: Transformation<V>>(m: &M) -> V {
|
||||
m.inv_transformation()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transform_by<V, M: Transformation<V>>(m: &mut M, v: &V) {
|
||||
m.transform_by(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transformed<V, M: Transformation<V>>(m: &M, v: &V) -> M {
|
||||
m.transformed(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn set_transformation<V, M: Transformation<V>>(m: &mut M, v: V) {
|
||||
m.set_transformation(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
|
||||
m.transform(v)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn inv_transform<V, M: Transform<V>>(m: &M, v: &V) -> V {
|
||||
m.inv_transform(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Dot<N>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn dot<V: Dot<N>, N>(a: &V, b: &V) -> N {
|
||||
a.dot(b)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn sub_dot<V: Dot<N>, N>(a: &V, b: &V, c: &V) -> N {
|
||||
a.sub_dot(b, c)
|
||||
}
|
||||
|
||||
/*
|
||||
* Norm<N>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn norm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
|
||||
v.norm()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn sqnorm<V: Norm<N>, N: Algebraic>(v: &V) -> N {
|
||||
v.sqnorm()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn normalized<V: Norm<N>, N: Algebraic>(v: &V) -> V {
|
||||
v.normalized()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn normalize<V: Norm<N>, N: Algebraic>(v: &mut V) -> N {
|
||||
v.normalize()
|
||||
}
|
||||
|
||||
/*
|
||||
* Cross<V>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn cross<LV: Cross<AV>, AV>(a: &LV, b: &LV) -> AV {
|
||||
a.cross(b)
|
||||
}
|
||||
|
||||
/*
|
||||
* CrossMatrix<M>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn cross_matrix<V: CrossMatrix<M>, M>(v: &V) -> M {
|
||||
v.cross_matrix()
|
||||
}
|
||||
|
||||
/*
|
||||
* ToHomogeneous<U>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn to_homogeneous<M: ToHomogeneous<Res>, Res>(m: &M) -> Res {
|
||||
m.to_homogeneous()
|
||||
}
|
||||
|
||||
/*
|
||||
* FromHomogeneous<U>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn from_homogeneous<M, Res: FromHomogeneous<M>>(m: &M) -> Res {
|
||||
FromHomogeneous::from(m)
|
||||
}
|
||||
|
||||
/*
|
||||
* UniformSphereSample
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn sample_sphere<V: UniformSphereSample>(f: &fn(V)) {
|
||||
UniformSphereSample::sample(f)
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Operations
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
/*
|
||||
* Absolute<A>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn absolute<M: Absolute<Res>, Res>(m: &M) -> Res {
|
||||
m.absolute()
|
||||
}
|
||||
|
||||
/*
|
||||
* Inv
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn inverted<M: Inv>(m: &M) -> Option<M> {
|
||||
m.inverted()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn invert<M: Inv>(m: &mut M) -> bool {
|
||||
m.invert()
|
||||
}
|
||||
|
||||
/*
|
||||
* Transpose
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transposed<M: Transpose>(m: &M) -> M {
|
||||
m.transposed()
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn transpose<M: Transpose>(m: &mut M) {
|
||||
m.transpose()
|
||||
}
|
||||
|
||||
/*
|
||||
* Outer<M>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn outer<V: Outer<M>, M>(a: &V, b: &V) -> M {
|
||||
a.outer(b)
|
||||
}
|
||||
|
||||
/*
|
||||
* Cov<M>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn cov<M: Cov<Res>, Res>(observations: &M) -> Res {
|
||||
observations.cov()
|
||||
}
|
||||
|
||||
/*
|
||||
* Mean<N>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
|
||||
observations.mean()
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Structure
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
* MatCast<M>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn cast_mat<M: MatCast<Res>, Res>(m: M) -> Res {
|
||||
MatCast::from(m)
|
||||
}
|
||||
|
||||
/*
|
||||
* VecCast<M>
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn cast_vec<V: VecCast<Res>, Res>(v: V) -> Res {
|
||||
VecCast::from(v)
|
||||
}
|
||||
|
||||
/*
|
||||
* Basis
|
||||
*/
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn canonical_basis<V: Basis>(f: &fn(V) -> bool) {
|
||||
Basis::canonical_basis(f)
|
||||
}
|
||||
|
||||
/// FIXME
|
||||
#[inline(always)]
|
||||
pub fn orthonormal_subspace_basis<V: Basis>(v: &V, f: &fn(V) -> bool) {
|
||||
v.orthonormal_subspace_basis(f)
|
||||
}
|
||||
|
||||
/*
|
||||
* Row<R>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Col<C>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dim
|
||||
*/
|
||||
|
||||
/*
|
||||
* Indexable
|
||||
*/
|
27
src/structs/chol.rs
Normal file
27
src/structs/chol.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// use lower_triangular::LowerTriangularMat;
|
||||
//
|
||||
// /// Choleski factorization.
|
||||
// pub trait Chol<N> {
|
||||
// /// Choleski LL* factorization for a symetric definite positive matrix.
|
||||
// fn chol(self) -> LowerTriangularMat<N>;
|
||||
// }
|
||||
//
|
||||
// impl<N> Chol<N> for DMat<N> {
|
||||
// fn chol(self) -> LowerTriangularMat<N> {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<N> Chol<N> for LowerTriangularMat<N> {
|
||||
// fn chol(self) -> LowerTriangularMat<N> {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<N> Chol<N> for UpperTriangularMat<N> {
|
||||
// fn chol(self) -> LowerTriangularMat<N> {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<N> Chol<N> for DiagonalMat<N> {
|
||||
// fn chol(self) -> LowerTriangularMat<N> {
|
||||
// }
|
||||
// }
|
6
src/structs/crout.rs
Normal file
6
src/structs/crout.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use lower_triangular::LowerTriangularMat;
|
||||
|
||||
pub trait Crout<N> {
|
||||
/// Crout LDL* factorization for a symetric definite indefinite matrix.
|
||||
fn crout(self, &mut DiagonalMat<N>) -> LowerTriangularMat<N>;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
//! Matrix with dimensions unknown at compile-time.
|
||||
|
||||
#[doc(hidden)]; // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
#[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
|
||||
use std::rand::Rand;
|
||||
use std::rand;
|
||||
@ -8,7 +8,7 @@ use std::num::{One, Zero};
|
||||
use std::vec;
|
||||
use std::cmp::ApproxEq;
|
||||
use std::util;
|
||||
use dvec::{DVec, DVecMulRhs};
|
||||
use structs::dvec::{DVec, DVecMulRhs};
|
||||
use traits::operations::{Inv, Transpose, Mean, Cov};
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -277,10 +277,10 @@ DVecMulRhs<N, DVec<N>> for DMat<N> {
|
||||
impl<N: Clone + Num>
|
||||
Inv for DMat<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<DMat<N>> {
|
||||
fn inverted(&self) -> Option<DMat<N>> {
|
||||
let mut res : DMat<N> = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
if res.invert() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
@ -288,7 +288,7 @@ Inv for DMat<N> {
|
||||
}
|
||||
}
|
||||
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
assert!(self.nrows == self.ncols);
|
||||
|
||||
let dim = self.nrows;
|
@ -1,6 +1,6 @@
|
||||
//! Vector with dimensions unknown at compile-time.
|
||||
|
||||
#[doc(hidden)]; // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
#[allow(missing_doc)]; // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
|
||||
use std::num::{Zero, One, Algebraic};
|
||||
use std::rand::Rand;
|
115
src/structs/iso.rs
Normal file
115
src/structs/iso.rs
Normal file
@ -0,0 +1,115 @@
|
||||
//! Isometric transformations.
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use std::num::{Zero, One};
|
||||
use std::rand::{Rand, Rng};
|
||||
use structs::mat::{Mat3, Mat4, Mat5};
|
||||
use traits::structure::{Dim, Col};
|
||||
use traits::operations::{Inv};
|
||||
use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation,
|
||||
Translate, Translation, ToHomogeneous};
|
||||
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
|
||||
use structs::rot::{Rot2, Rot3, Rot4};
|
||||
|
||||
mod metal;
|
||||
mod iso_macros;
|
||||
|
||||
/// Two dimensional isometry.
|
||||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Iso2<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot2<N>,
|
||||
/// The translation applicable by this isometry.
|
||||
translation: Vec2<N>
|
||||
}
|
||||
|
||||
/// Three dimensional isometry.
|
||||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Iso3<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot3<N>,
|
||||
/// The translation applicable by this isometry.
|
||||
translation: Vec3<N>
|
||||
}
|
||||
|
||||
/// Four dimensional isometry.
|
||||
///
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Iso4<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
rotation: Rot4<N>,
|
||||
/// The translation applicable by this isometry.
|
||||
translation: Vec4<N>
|
||||
}
|
||||
|
||||
iso_impl!(Iso2, Rot2, Vec2)
|
||||
double_dispatch_binop_decl_trait!(Iso2, Iso2MulRhs)
|
||||
mul_redispatch_impl!(Iso2, Iso2MulRhs)
|
||||
rotation_matrix_impl!(Iso2, Rot2, Vec2, Vec1)
|
||||
rotation_impl!(Iso2, Rot2, Vec1)
|
||||
dim_impl!(Iso2, 2)
|
||||
one_impl!(Iso2)
|
||||
absolute_rotate_impl!(Iso2, Vec2)
|
||||
rand_impl!(Iso2)
|
||||
approx_eq_impl!(Iso2)
|
||||
to_homogeneous_impl!(Iso2, Mat3)
|
||||
inv_impl!(Iso2)
|
||||
transform_impl!(Iso2, Vec2)
|
||||
transformation_impl!(Iso2)
|
||||
rotate_impl!(Iso2, Vec2)
|
||||
translation_impl!(Iso2, Vec2)
|
||||
translate_impl!(Iso2, Vec2)
|
||||
iso_mul_iso_impl!(Iso2, Iso2MulRhs)
|
||||
iso_mul_vec_impl!(Iso2, Vec2, Iso2MulRhs)
|
||||
vec_mul_iso_impl!(Iso2, Vec2, Vec2MulRhs)
|
||||
|
||||
iso_impl!(Iso3, Rot3, Vec3)
|
||||
double_dispatch_binop_decl_trait!(Iso3, Iso3MulRhs)
|
||||
mul_redispatch_impl!(Iso3, Iso3MulRhs)
|
||||
rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3)
|
||||
rotation_impl!(Iso3, Rot3, Vec3)
|
||||
dim_impl!(Iso3, 3)
|
||||
one_impl!(Iso3)
|
||||
absolute_rotate_impl!(Iso3, Vec3)
|
||||
rand_impl!(Iso3)
|
||||
approx_eq_impl!(Iso3)
|
||||
to_homogeneous_impl!(Iso3, Mat4)
|
||||
inv_impl!(Iso3)
|
||||
transform_impl!(Iso3, Vec3)
|
||||
transformation_impl!(Iso3)
|
||||
rotate_impl!(Iso3, Vec3)
|
||||
translation_impl!(Iso3, Vec3)
|
||||
translate_impl!(Iso3, Vec3)
|
||||
iso_mul_iso_impl!(Iso3, Iso3MulRhs)
|
||||
iso_mul_vec_impl!(Iso3, Vec3, Iso3MulRhs)
|
||||
vec_mul_iso_impl!(Iso3, Vec3, Vec3MulRhs)
|
||||
|
||||
iso_impl!(Iso4, Rot4, Vec4)
|
||||
double_dispatch_binop_decl_trait!(Iso4, Iso4MulRhs)
|
||||
mul_redispatch_impl!(Iso4, Iso4MulRhs)
|
||||
// rotation_matrix_impl!(Iso4, Rot4, Vec4, Vec4)
|
||||
// rotation_impl!(Iso4, Rot4, Vec4)
|
||||
dim_impl!(Iso4, 4)
|
||||
one_impl!(Iso4)
|
||||
// absolute_rotate_impl!(Iso4, Vec4)
|
||||
// rand_impl!(Iso4)
|
||||
approx_eq_impl!(Iso4)
|
||||
to_homogeneous_impl!(Iso4, Mat5)
|
||||
inv_impl!(Iso4)
|
||||
transform_impl!(Iso4, Vec4)
|
||||
transformation_impl!(Iso4)
|
||||
// rotate_impl!(Iso4, Vec4)
|
||||
translation_impl!(Iso4, Vec4)
|
||||
translate_impl!(Iso4, Vec4)
|
||||
iso_mul_iso_impl!(Iso4, Iso4MulRhs)
|
||||
iso_mul_vec_impl!(Iso4, Vec4, Iso4MulRhs)
|
||||
vec_mul_iso_impl!(Iso4, Vec4, Vec4MulRhs)
|
319
src/structs/iso_macros.rs
Normal file
319
src/structs/iso_macros.rs
Normal file
@ -0,0 +1,319 @@
|
||||
#[macro_escape];
|
||||
|
||||
macro_rules! iso_impl(
|
||||
($t: ident, $submat: ident, $subvec: ident) => (
|
||||
impl<N> $t<N> {
|
||||
/// Creates a new isometry from a rotation matrix and a vector.
|
||||
#[inline]
|
||||
pub fn new(translation: $subvec<N>, rotation: $submat<N>) -> $t<N> {
|
||||
$t {
|
||||
rotation: rotation,
|
||||
translation: translation
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rotation_matrix_impl(
|
||||
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
|
||||
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
|
||||
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> $trot<N> {
|
||||
self.rotation.clone()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N> Dim for $t<N> {
|
||||
#[inline]
|
||||
fn dim(_: Option<$t<N>>) -> uint {
|
||||
$dim
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident) => (
|
||||
impl<N: One + Zero + Clone> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new(Zero::zero(), One::one())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! iso_mul_iso_impl(
|
||||
($t: ident, $tmul: ident) => (
|
||||
impl<N: Num + Clone> $tmul<N, $t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
|
||||
$t::new(left.translation + left.rotation * right.translation, left.rotation * right.rotation)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! iso_mul_vec_impl(
|
||||
($t: ident, $tv: ident, $tmul: ident) => (
|
||||
impl<N: Num + Clone> $tmul<N, $tv<N>> for $tv<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
|
||||
left.translation + left.rotation * *right
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! vec_mul_iso_impl(
|
||||
($t: ident, $tv: ident, $tmul: ident) => (
|
||||
impl<N: Clone + Num> $tmul<N, $tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$tv<N>, right: &$t<N>) -> $tv<N> {
|
||||
(left + right.translation) * right.rotation
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! translation_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Neg<N> + Add<N, N> + Clone> Translation<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn translation(&self) -> $tv<N> {
|
||||
self.translation.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_translation(&self) -> $tv<N> {
|
||||
-self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn translate_by(&mut self, t: &$tv<N>) {
|
||||
self.translation = self.translation + *t
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn translated(&self, t: &$tv<N>) -> $t<N> {
|
||||
$t::new(self.translation + *t, self.rotation.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_translation(&mut self, t: $tv<N>) {
|
||||
self.translation = t
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! translate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Clone + Add<N, N> + Sub<N, N>> Translate<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn translate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
v + self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_translate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
v - self.translation
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rotation_impl(
|
||||
($t: ident, $trot: ident, $tav: ident) => (
|
||||
impl<N: Num + Trigonometric + Algebraic + NumCast + Clone> Rotation<$tav<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> $tav<N> {
|
||||
self.rotation.rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> $tav<N> {
|
||||
self.rotation.inv_rotation()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &$tav<N>) {
|
||||
// FIXME: this does not seem opitmal
|
||||
let mut delta: $trot<N> = One::one();
|
||||
delta.rotate_by(rot);
|
||||
self.rotation.rotate_by(rot);
|
||||
self.translation = delta * self.translation;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, rot: &$tav<N>) -> $t<N> {
|
||||
// FIXME: this does not seem opitmal
|
||||
let _1: $trot<N> = One::one();
|
||||
let delta = _1.rotated(rot);
|
||||
|
||||
$t::new(delta * self.translation, self.rotation.rotated(rot))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rot: $tav<N>) {
|
||||
// FIXME: should the translation be changed too?
|
||||
self.rotation.set_rotation(rot)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rotate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Num + Clone> Rotate<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotation.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotation.inv_rotate(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! transformation_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Num + Clone> Transformation<$t<N>> for $t<N> {
|
||||
fn transformation(&self) -> $t<N> {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
fn inv_transformation(&self) -> $t<N> {
|
||||
// inversion will never fails
|
||||
self.inverted().unwrap()
|
||||
}
|
||||
|
||||
fn transform_by(&mut self, other: &$t<N>) {
|
||||
*self = other * *self
|
||||
}
|
||||
|
||||
fn transformed(&self, t: &$t<N>) -> $t<N> {
|
||||
t * *self
|
||||
}
|
||||
|
||||
fn set_transformation(&mut self, t: $t<N>) {
|
||||
*self = t
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! transform_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotation.transform(v) + self.translation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotation.inv_transform(&(v - self.translation))
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! inv_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Clone + Num> Inv for $t<N> {
|
||||
#[inline]
|
||||
fn invert(&mut self) -> bool {
|
||||
self.rotation.invert();
|
||||
self.translation = self.rotation * -self.translation;
|
||||
|
||||
// always succeed
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverted(&self) -> Option<$t<N>> {
|
||||
let mut res = self.clone();
|
||||
|
||||
res.invert();
|
||||
|
||||
// always succeed
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! to_homogeneous_impl(
|
||||
($t: ident, $th: ident) => (
|
||||
impl<N: One + Zero + Clone> ToHomogeneous<$th<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $th<N> {
|
||||
let mut res = self.rotation.to_homogeneous();
|
||||
|
||||
// copy the translation
|
||||
let dim = Dim::dim(None::<$th<N>>);
|
||||
|
||||
res.set_col(dim - 1, self.translation.to_homogeneous());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! approx_eq_impl(
|
||||
($t: ident) => (
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> N {
|
||||
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
|
||||
// ApproxEq::<N>::approx_epsilon()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &$t<N>) -> bool {
|
||||
self.rotation.approx_eq(&other.rotation) &&
|
||||
self.translation.approx_eq(&other.translation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||
self.rotation.approx_eq_eps(&other.rotation, epsilon) &&
|
||||
self.translation.approx_eq_eps(&other.translation, epsilon)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rand_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Rand + Clone + Trigonometric + Algebraic + Num> Rand for $t<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||
$t::new(rng.gen(), rng.gen())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! absolute_rotate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Signed> AbsoluteRotate<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotation.absolute_rotate(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
153
src/structs/lower_triangular.rs
Normal file
153
src/structs/lower_triangular.rs
Normal file
@ -0,0 +1,153 @@
|
||||
use std::rand::Rand;
|
||||
use std::rand;
|
||||
use std::num::{One, Zero};
|
||||
use std::vec;
|
||||
|
||||
/// A structure optimized to store lower triangular matrices.
|
||||
pub struct LowerTriangularMat<N> {
|
||||
priv dim: uint,
|
||||
priv mij: ~[N]
|
||||
}
|
||||
|
||||
/// Trait to be implemented by objects which can be left-multiplied by a lower triangular array.
|
||||
pub trait LowerTriangularMatMulRhs<N, Res> {
|
||||
/// Apply the muliplicitaion.
|
||||
fn binop(left: &LowerTriangularMat<N>, right: &Self) -> Res;
|
||||
}
|
||||
|
||||
impl<N, Rhs: LowerTriangularMatMulRhs<N, Res>, Res> Mul<Rhs, Res> for LowerTriangularMat<N> {
|
||||
#[inline(always)]
|
||||
fn mul(&self, other: &Rhs) -> Res {
|
||||
LowerTriangularMatMulRhs::binop(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix without initializing its arguments.
|
||||
#[inline]
|
||||
pub unsafe fn new_uninitialized(dim: uint) -> LowerTriangularMat<N> {
|
||||
let mut vec = vec::with_capacity(dim * (dim + 1) / 2);
|
||||
vec::raw::set_len(&mut vec, dim * (dim + 1) / 2);
|
||||
|
||||
LowerTriangularMat {
|
||||
dim: dim,
|
||||
mij: vec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Zero + Clone> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix filled with zeros.
|
||||
#[inline]
|
||||
pub fn new_zeros(dim: uint) -> LowerTriangularMat<N> {
|
||||
LowerTriangularMat::from_elem(dim, Zero::zero())
|
||||
}
|
||||
|
||||
/// Tests if every entry of the matrix are exactly zeros.
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.mij.iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Rand> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix filled with random elements.
|
||||
#[inline]
|
||||
pub fn new_random(dim: uint) -> LowerTriangularMat<N> {
|
||||
LowerTriangularMat::from_fn(dim, |_, _| rand::random())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: One + Clone> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix filled with ones.
|
||||
#[inline]
|
||||
pub fn new_ones(dim: uint) -> LowerTriangularMat<N> {
|
||||
LowerTriangularMat::from_elem(dim, One::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix filled with a given value.
|
||||
#[inline]
|
||||
pub fn from_elem(dim: uint, val: N) -> LowerTriangularMat<N> {
|
||||
LowerTriangularMat {
|
||||
dim: dim,
|
||||
mij: vec::from_elem(dim * (dim + 1) / 2, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> LowerTriangularMat<N> {
|
||||
/// Creates a lower triangular matrix filled by a function.
|
||||
#[inline(always)]
|
||||
pub fn from_fn(dim: uint, f: &fn(uint, uint) -> N) -> LowerTriangularMat<N> {
|
||||
let mij = do vec::from_fn(dim * (dim + 1) / 2) |i| {
|
||||
let l = (((1.0f64 + 8.0f64 * i as f64).sqrt() - 1.) / 2.0f64).floor() as uint;
|
||||
let c = i - l * (l + 1) / 2;
|
||||
|
||||
f(l, c)
|
||||
};
|
||||
|
||||
LowerTriangularMat {
|
||||
dim: dim,
|
||||
mij: mij
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset(&self, i: uint, j: uint) -> uint {
|
||||
i * (i + 1) / 2 + j + 1
|
||||
}
|
||||
|
||||
/// Transforms this matrix into an array. This consumes the matrix and is O(1).
|
||||
#[inline]
|
||||
pub fn to_array(self) -> ~[N] {
|
||||
self.mij
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Zero + Clone> LowerTriangularMat<N> {
|
||||
/// Changes the value of a component of the matrix.
|
||||
/// Fails if the indices point outside of the lower-triangular part of the matrix.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `row` - 0-based index of the line to be changed
|
||||
/// * `col` - 0-based index of the column to be changed
|
||||
#[inline]
|
||||
pub fn set(&mut self, row: uint, col: uint, val: N) {
|
||||
assert!(row < self.dim);
|
||||
assert!(col < self.dim);
|
||||
assert!(col <= row);
|
||||
unsafe { self.set_fast(row, col, val) }
|
||||
}
|
||||
|
||||
/// Just like `set` without bounds checking.
|
||||
#[inline]
|
||||
pub unsafe fn set_fast(&mut self, row: uint, col: uint, val: N) {
|
||||
let offset = self.offset(row, col);
|
||||
*self.mij.unsafe_mut_ref(offset) = val
|
||||
}
|
||||
|
||||
/// Reads the value of a component of the matrix.
|
||||
/// Fails if the indices point outside of the lower-triangular part of the matrix.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `row` - 0-based index of the line to be read
|
||||
/// * `col` - 0-based index of the column to be read
|
||||
#[inline]
|
||||
pub fn at(&self, row: uint, col: uint) -> N {
|
||||
assert!(row < self.dim);
|
||||
assert!(col < self.dim);
|
||||
unsafe { self.at_fast(row, col) }
|
||||
}
|
||||
|
||||
/// Just like `at` without bounds checking.
|
||||
#[inline]
|
||||
pub unsafe fn at_fast(&self, row: uint, col: uint) -> N {
|
||||
if col > row {
|
||||
Zero::zero()
|
||||
}
|
||||
|
||||
vec::raw::get(self.mij, self.offset(row, col))
|
||||
}
|
||||
}
|
@ -6,17 +6,12 @@ use std::cast;
|
||||
use std::num::{One, Zero};
|
||||
use std::cmp::ApproxEq;
|
||||
use std::vec::{VecIterator, VecMutIterator};
|
||||
use vec::*;
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
|
||||
Vec5MulRhs, Vec6MulRhs};
|
||||
|
||||
// traits
|
||||
pub use traits::structure::{Mat, Dim, Indexable, Iterable, IterableMut, MatCast, Row, Col};
|
||||
pub use traits::operations::{Absolute, ScalarSub, ScalarAdd, Inv, RMul, Transpose, Mean, Cov};
|
||||
pub use traits::geometry::{Rotation, RotationMatrix, Rotate, Transformation, Transform,
|
||||
Translation, Translate, ToHomogeneous, FromHomogeneous,
|
||||
RotationWithTranslation, AbsoluteRotate};
|
||||
|
||||
// structs
|
||||
pub use dmat::DMat;
|
||||
use traits::structure::{MatCast, Row, Col, Iterable, IterableMut, Dim, Indexable};
|
||||
use traits::operations::{Absolute, Transpose, Inv, Outer};
|
||||
use traits::geometry::{ToHomogeneous, FromHomogeneous};
|
||||
|
||||
mod metal;
|
||||
mod mat_macros;
|
||||
@ -118,7 +113,6 @@ indexable_impl!(Mat1, 1)
|
||||
mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1)
|
||||
mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1)
|
||||
vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1)
|
||||
transform_impl!(Mat1, Vec1)
|
||||
// (specialized) inv_impl!(Mat1, 1)
|
||||
transpose_impl!(Mat1, 1)
|
||||
approx_eq_impl!(Mat1)
|
||||
@ -214,7 +208,6 @@ at_fast_impl!(Mat2, 2)
|
||||
// (specialized) mul_impl!(Mat2, 2)
|
||||
// (specialized) rmul_impl!(Mat2, Vec2, 2)
|
||||
// (specialized) lmul_impl!(Mat2, Vec2, 2)
|
||||
transform_impl!(Mat2, Vec2)
|
||||
// (specialized) inv_impl!(Mat2, 2)
|
||||
transpose_impl!(Mat2, 2)
|
||||
approx_eq_impl!(Mat2)
|
||||
@ -324,7 +317,6 @@ at_fast_impl!(Mat3, 3)
|
||||
// (specialized) mul_impl!(Mat3, 3)
|
||||
// (specialized) rmul_impl!(Mat3, Vec3, 3)
|
||||
// (specialized) lmul_impl!(Mat3, Vec3, 3)
|
||||
transform_impl!(Mat3, Vec3)
|
||||
// (specialized) inv_impl!(Mat3, 3)
|
||||
transpose_impl!(Mat3, 3)
|
||||
approx_eq_impl!(Mat3)
|
||||
@ -486,7 +478,6 @@ at_fast_impl!(Mat4, 4)
|
||||
mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4)
|
||||
mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4)
|
||||
vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4)
|
||||
transform_impl!(Mat4, Vec4)
|
||||
inv_impl!(Mat4, 4)
|
||||
transpose_impl!(Mat4, 4)
|
||||
approx_eq_impl!(Mat4)
|
||||
@ -664,7 +655,6 @@ at_fast_impl!(Mat5, 5)
|
||||
mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5)
|
||||
mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5)
|
||||
vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5)
|
||||
transform_impl!(Mat5, Vec5)
|
||||
inv_impl!(Mat5, 5)
|
||||
transpose_impl!(Mat5, 5)
|
||||
approx_eq_impl!(Mat5)
|
||||
@ -894,7 +884,6 @@ at_fast_impl!(Mat6, 6)
|
||||
mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6)
|
||||
mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6)
|
||||
vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6)
|
||||
transform_impl!(Mat6, Vec6)
|
||||
inv_impl!(Mat6, 6)
|
||||
transpose_impl!(Mat6, 6)
|
||||
approx_eq_impl!(Mat6)
|
@ -200,7 +200,7 @@ macro_rules! row_impl(
|
||||
($t: ident, $tv: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn num_rows(&self) -> uint {
|
||||
fn nrows(&self) -> uint {
|
||||
Dim::dim(None::<$t<N>>)
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ macro_rules! col_impl(
|
||||
($t: ident, $tv: ident, $dim: expr) => (
|
||||
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn num_cols(&self) -> uint {
|
||||
fn ncols(&self) -> uint {
|
||||
Dim::dim(None::<$t<N>>)
|
||||
}
|
||||
|
||||
@ -326,35 +326,15 @@ macro_rules! mat_mul_vec_impl(
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! transform_impl(
|
||||
($t: ident, $v: ident) => (
|
||||
impl<N: Clone + Num + Eq>
|
||||
Transform<$v<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &$v<N>) -> $v<N> {
|
||||
self.rmul(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, v: &$v<N>) -> $v<N> {
|
||||
match self.inverse() {
|
||||
Some(t) => t.transform(v),
|
||||
None => fail!("Cannot use inv_transform on a non-inversible matrix.")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! inv_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N: Clone + Eq + Num>
|
||||
Inv for $t<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<$t<N>> {
|
||||
fn inverted(&self) -> Option<$t<N>> {
|
||||
let mut res : $t<N> = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
if res.invert() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
@ -362,7 +342,7 @@ macro_rules! inv_impl(
|
||||
}
|
||||
}
|
||||
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
let mut res: $t<N> = One::one();
|
||||
let _0N: N = Zero::zero();
|
||||
|
||||
@ -528,7 +508,7 @@ macro_rules! from_homogeneous_impl(
|
||||
|
||||
macro_rules! outer_impl(
|
||||
($t: ident, $m: ident) => (
|
||||
impl<N: Mul<N, N> + Zero + Clone> Outer<$t<N>, $m<N>> for $t<N> {
|
||||
impl<N: Mul<N, N> + Zero + Clone> Outer<$m<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn outer(&self, other: &$t<N>) -> $m<N> {
|
||||
let mut res: $m<N> = Zero::zero();
|
25
src/structs/mod.rs
Normal file
25
src/structs/mod.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! Data structures and implementations.
|
||||
|
||||
pub use self::dmat::DMat;
|
||||
pub use self::dvec::DVec;
|
||||
pub use self::vec::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
|
||||
pub use self::mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
||||
pub use self::rot::{Rot2, Rot3, Rot4};
|
||||
pub use self::iso::{Iso2, Iso3, Iso4};
|
||||
|
||||
pub mod dmat;
|
||||
pub mod dvec;
|
||||
pub mod vec;
|
||||
pub mod mat;
|
||||
pub mod rot;
|
||||
pub mod iso;
|
||||
|
||||
// specialization for some 1d, 2d and 3d operations
|
||||
#[doc(hidden)]
|
||||
mod spec {
|
||||
mod identity;
|
||||
mod mat;
|
||||
mod vec0;
|
||||
mod vec;
|
||||
// mod complex;
|
||||
}
|
328
src/structs/rot.rs
Normal file
328
src/structs/rot.rs
Normal file
@ -0,0 +1,328 @@
|
||||
//! Rotations matrices.
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use std::num::{Zero, One};
|
||||
use std::rand::{Rand, Rng};
|
||||
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
|
||||
Norm, Cross};
|
||||
use traits::structure::{Dim, Indexable, Row, Col};
|
||||
use traits::operations::{Absolute, Inv, Transpose};
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec2MulRhs, Vec3MulRhs, Vec4MulRhs};
|
||||
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
|
||||
|
||||
mod metal;
|
||||
mod rot_macros;
|
||||
|
||||
/// Two dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Rot2<N> {
|
||||
priv submat: Mat2<N>
|
||||
}
|
||||
|
||||
impl<N: Clone + Trigonometric + Neg<N>> Rot2<N> {
|
||||
/// Builds a 2 dimensional rotation matrix from an angle in radian.
|
||||
pub fn from_angle(angle: N) -> Rot2<N> {
|
||||
let (sia, coa) = angle.sin_cos();
|
||||
|
||||
Rot2 {
|
||||
submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Trigonometric + Num + Clone>
|
||||
Rotation<Vec1<N>> for Rot2<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec1<N> {
|
||||
Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0))))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec1<N> {
|
||||
-self.rotation()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &Vec1<N>) {
|
||||
*self = self.rotated(rot)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, rot: &Vec1<N>) -> Rot2<N> {
|
||||
Rot2::from_angle(rot.x.clone()) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rot: Vec1<N>) {
|
||||
*self = Rot2::from_angle(rot.x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rot2<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
|
||||
Rot2::from_angle(rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec2<N>> for Rot2<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec2<N>) -> Vec2<N> {
|
||||
// the matrix is skew-symetric, so we dont need to compute the absolute value of every
|
||||
// component.
|
||||
let m11 = self.submat.m11.abs();
|
||||
let m12 = self.submat.m12.abs();
|
||||
let m22 = self.submat.m22.abs();
|
||||
|
||||
Vec2::new(m11 * v.x + m12 * v.y, m12 * v.x + m22 * v.y)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 3d rotation
|
||||
*/
|
||||
/// Three dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Rot3<N> {
|
||||
priv submat: Mat3<N>
|
||||
}
|
||||
|
||||
|
||||
impl<N: Clone + Trigonometric + Num + Algebraic> Rot3<N> {
|
||||
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `axisangle` - A vector representing the rotation. Its magnitude is the amount of rotation
|
||||
/// in radian. Its direction is the axis of rotation.
|
||||
pub fn from_axis_angle(axisangle: Vec3<N>) -> Rot3<N> {
|
||||
if axisangle.sqnorm().is_zero() {
|
||||
One::one()
|
||||
}
|
||||
else {
|
||||
let mut axis = axisangle;
|
||||
let angle = axis.normalize();
|
||||
let _1: N = One::one();
|
||||
let ux = axis.x.clone();
|
||||
let uy = axis.y.clone();
|
||||
let uz = axis.z.clone();
|
||||
let sqx = ux * ux;
|
||||
let sqy = uy * uy;
|
||||
let sqz = uz * uz;
|
||||
let (sin, cos) = angle.sin_cos();
|
||||
let one_m_cos = _1 - cos;
|
||||
|
||||
Rot3 {
|
||||
submat: Mat3::new(
|
||||
(sqx + (_1 - sqx) * cos),
|
||||
(ux * uy * one_m_cos - uz * sin),
|
||||
(ux * uz * one_m_cos + uy * sin),
|
||||
|
||||
(ux * uy * one_m_cos + uz * sin),
|
||||
(sqy + (_1 - sqy) * cos),
|
||||
(uy * uz * one_m_cos - ux * sin),
|
||||
|
||||
(ux * uz * one_m_cos - uy * sin),
|
||||
(uy * uz * one_m_cos + ux * sin),
|
||||
(sqz + (_1 - sqz) * cos))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Num + Algebraic> Rot3<N> {
|
||||
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
|
||||
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
|
||||
/// for that.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * at - The point to look at. It is also the direction the matrix `x` axis will be aligned
|
||||
/// with
|
||||
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
let xaxis = at.normalized();
|
||||
let zaxis = up.cross(&xaxis).normalized();
|
||||
let yaxis = zaxis.cross(&xaxis);
|
||||
|
||||
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
|
||||
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
|
||||
xaxis.z , yaxis.z , zaxis.z)
|
||||
}
|
||||
|
||||
/// Reorient this matrix such that its local `z` axis points to a given point.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * at - The point to look at. It is also the direction the matrix `y` axis will be aligned
|
||||
/// with
|
||||
/// * up - Vector pointing `up`. The only requirement of this parameter is to not be colinear
|
||||
/// with `at`. Non-colinearity is not checked.
|
||||
pub fn look_at_z(&mut self, at: &Vec3<N>, up: &Vec3<N>) {
|
||||
let zaxis = at.normalized();
|
||||
let xaxis = up.cross(&zaxis).normalized();
|
||||
let yaxis = zaxis.cross(&xaxis);
|
||||
|
||||
self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
|
||||
xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
|
||||
xaxis.z , yaxis.z , zaxis.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Trigonometric + Num + Algebraic + NumCast>
|
||||
Rotation<Vec3<N>> for Rot3<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec3<N> {
|
||||
let angle = ((self.submat.m11 + self.submat.m22 + self.submat.m33 - One::one()) / NumCast::from(2.0)).acos();
|
||||
|
||||
if angle != angle {
|
||||
// FIXME: handle that correctly
|
||||
Zero::zero()
|
||||
}
|
||||
else if angle.is_zero() {
|
||||
Zero::zero()
|
||||
}
|
||||
else {
|
||||
let m32_m23 = self.submat.m32 - self.submat.m23;
|
||||
let m13_m31 = self.submat.m13 - self.submat.m31;
|
||||
let m21_m12 = self.submat.m21 - self.submat.m12;
|
||||
|
||||
let denom = (m32_m23 * m32_m23 + m13_m31 * m13_m31 + m21_m12 * m21_m12).sqrt();
|
||||
|
||||
if denom.is_zero() {
|
||||
// XXX: handle that properly
|
||||
// fail!("Internal error: singularity.")
|
||||
Zero::zero()
|
||||
}
|
||||
else {
|
||||
let a_d = angle / denom;
|
||||
|
||||
Vec3::new(m32_m23 * a_d, m13_m31 * a_d, m21_m12 * a_d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec3<N> {
|
||||
-self.rotation()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rot: &Vec3<N>) {
|
||||
*self = self.rotated(rot)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, axisangle: &Vec3<N>) -> Rot3<N> {
|
||||
Rot3::from_axis_angle(axisangle.clone()) * *self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, axisangle: Vec3<N>) {
|
||||
*self = Rot3::from_axis_angle(axisangle)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
|
||||
Rand for Rot3<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
|
||||
Rot3::from_axis_angle(rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec3<N>> for Rot3<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec3<N>) -> Vec3<N> {
|
||||
Vec3::new(
|
||||
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y + self.submat.m13.abs() * v.z,
|
||||
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y + self.submat.m23.abs() * v.z,
|
||||
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y + self.submat.m33.abs() * v.z)
|
||||
}
|
||||
}
|
||||
|
||||
/// Four dimensional rotation matrix.
|
||||
#[deriving(Eq, Encodable, Decodable, Clone, DeepClone, ToStr)]
|
||||
pub struct Rot4<N> {
|
||||
priv submat: Mat4<N>
|
||||
}
|
||||
|
||||
impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rot4<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec4<N>) -> Vec4<N> {
|
||||
Vec4::new(
|
||||
self.submat.m11.abs() * v.x + self.submat.m12.abs() * v.y +
|
||||
self.submat.m13.abs() * v.z + self.submat.m14.abs() * v.w,
|
||||
|
||||
self.submat.m21.abs() * v.x + self.submat.m22.abs() * v.y +
|
||||
self.submat.m23.abs() * v.z + self.submat.m24.abs() * v.w,
|
||||
|
||||
self.submat.m31.abs() * v.x + self.submat.m32.abs() * v.y +
|
||||
self.submat.m33.abs() * v.z + self.submat.m34.abs() * v.w,
|
||||
|
||||
self.submat.m41.abs() * v.x + self.submat.m42.abs() * v.y +
|
||||
self.submat.m43.abs() * v.z + self.submat.m44.abs() * v.w)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common implementations.
|
||||
*/
|
||||
|
||||
double_dispatch_binop_decl_trait!(Rot2, Rot2MulRhs)
|
||||
mul_redispatch_impl!(Rot2, Rot2MulRhs)
|
||||
submat_impl!(Rot2, Mat2)
|
||||
rotate_impl!(Rot2, Vec2)
|
||||
transform_impl!(Rot2, Vec2)
|
||||
dim_impl!(Rot2, 2)
|
||||
rot_mul_rot_impl!(Rot2, Rot2MulRhs)
|
||||
rot_mul_vec_impl!(Rot2, Vec2, Rot2MulRhs)
|
||||
vec_mul_rot_impl!(Rot2, Vec2, Vec2MulRhs)
|
||||
one_impl!(Rot2)
|
||||
rotation_matrix_impl!(Rot2, Vec2, Vec1)
|
||||
col_impl!(Rot2, Vec2)
|
||||
row_impl!(Rot2, Vec2)
|
||||
absolute_impl!(Rot2, Mat2)
|
||||
to_homogeneous_impl!(Rot2, Mat3)
|
||||
inv_impl!(Rot2)
|
||||
transpose_impl!(Rot2)
|
||||
approx_eq_impl!(Rot2)
|
||||
|
||||
double_dispatch_binop_decl_trait!(Rot3, Rot3MulRhs)
|
||||
mul_redispatch_impl!(Rot3, Rot3MulRhs)
|
||||
submat_impl!(Rot3, Mat3)
|
||||
rotate_impl!(Rot3, Vec3)
|
||||
transform_impl!(Rot3, Vec3)
|
||||
dim_impl!(Rot3, 3)
|
||||
rot_mul_rot_impl!(Rot3, Rot3MulRhs)
|
||||
rot_mul_vec_impl!(Rot3, Vec3, Rot3MulRhs)
|
||||
vec_mul_rot_impl!(Rot3, Vec3, Vec3MulRhs)
|
||||
one_impl!(Rot3)
|
||||
rotation_matrix_impl!(Rot3, Vec3, Vec3)
|
||||
col_impl!(Rot3, Vec3)
|
||||
row_impl!(Rot3, Vec3)
|
||||
absolute_impl!(Rot3, Mat3)
|
||||
to_homogeneous_impl!(Rot3, Mat4)
|
||||
inv_impl!(Rot3)
|
||||
transpose_impl!(Rot3)
|
||||
approx_eq_impl!(Rot3)
|
||||
|
||||
double_dispatch_binop_decl_trait!(Rot4, Rot4MulRhs)
|
||||
mul_redispatch_impl!(Rot4, Rot4MulRhs)
|
||||
submat_impl!(Rot4, Mat4)
|
||||
rotate_impl!(Rot4, Vec4)
|
||||
transform_impl!(Rot4, Vec4)
|
||||
dim_impl!(Rot4, 4)
|
||||
rot_mul_rot_impl!(Rot4, Rot4MulRhs)
|
||||
rot_mul_vec_impl!(Rot4, Vec4, Rot4MulRhs)
|
||||
vec_mul_rot_impl!(Rot4, Vec4, Vec4MulRhs)
|
||||
one_impl!(Rot4)
|
||||
// rotation_matrix_impl!(Rot4, Vec4, Vec4)
|
||||
col_impl!(Rot4, Vec4)
|
||||
row_impl!(Rot4, Vec4)
|
||||
absolute_impl!(Rot4, Mat4)
|
||||
to_homogeneous_impl!(Rot4, Mat5)
|
||||
inv_impl!(Rot4)
|
||||
transpose_impl!(Rot4)
|
||||
approx_eq_impl!(Rot4)
|
231
src/structs/rot_macros.rs
Normal file
231
src/structs/rot_macros.rs
Normal file
@ -0,0 +1,231 @@
|
||||
#[macro_escape];
|
||||
|
||||
macro_rules! submat_impl(
|
||||
($t: ident, $submat: ident) => (
|
||||
impl<N> $t<N> {
|
||||
#[inline]
|
||||
pub fn submat<'r>(&'r self) -> &'r $submat<N> {
|
||||
&'r self.submat
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rotate_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Num + Clone> Rotate<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self * *v
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotate(&self, v: &$tv<N>) -> $tv<N> {
|
||||
v * *self
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! transform_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Num + Clone> Transform<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.rotate(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, v: &$tv<N>) -> $tv<N> {
|
||||
self.inv_rotate(v)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! dim_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N> Dim for $t<N> {
|
||||
#[inline]
|
||||
fn dim(_: Option<$t<N>>) -> uint {
|
||||
$dim
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rotation_matrix_impl(
|
||||
($t: ident, $tlv: ident, $tav: ident) => (
|
||||
impl<N: NumCast + Algebraic + Trigonometric + Num + Clone>
|
||||
RotationMatrix<$tlv<N>, $tav<N>, $t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> $t<N> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t: ident) => (
|
||||
impl<N: One + Zero + Clone> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t { submat: One::one() }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rot_mul_rot_impl(
|
||||
($t: ident, $mulrhs: ident) => (
|
||||
impl<N: Num + Clone> $mulrhs<N, $t<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
|
||||
$t { submat: left.submat * right.submat }
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! rot_mul_vec_impl(
|
||||
($t: ident, $tv: ident, $mulrhs: ident) => (
|
||||
impl<N: Num + Clone> $mulrhs<N, $tv<N>> for $tv<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$t<N>, right: &$tv<N>) -> $tv<N> {
|
||||
left.submat * *right
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! vec_mul_rot_impl(
|
||||
($t: ident, $tv: ident, $mulrhs: ident) => (
|
||||
impl<N: Num + Clone> $mulrhs<N, $tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn binop(left: &$tv<N>, right: &$t<N>) -> $tv<N> {
|
||||
*left * right.submat
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! inv_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Clone> Inv for $t<N> {
|
||||
#[inline]
|
||||
fn invert(&mut self) -> bool {
|
||||
self.transpose();
|
||||
|
||||
// always succeed
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverted(&self) -> Option<$t<N>> {
|
||||
// always succeed
|
||||
Some(self.transposed())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! transpose_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Clone> Transpose for $t<N> {
|
||||
#[inline]
|
||||
fn transposed(&self) -> $t<N> {
|
||||
$t { submat: self.submat.transposed() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transpose(&mut self) {
|
||||
self.submat.transpose()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! row_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn nrows(&self) -> uint {
|
||||
self.submat.nrows()
|
||||
}
|
||||
#[inline]
|
||||
fn row(&self, i: uint) -> $tv<N> {
|
||||
self.submat.row(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_row(&mut self, i: uint, row: $tv<N>) {
|
||||
self.submat.set_row(i, row);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! col_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn ncols(&self) -> uint {
|
||||
self.submat.ncols()
|
||||
}
|
||||
#[inline]
|
||||
fn col(&self, i: uint) -> $tv<N> {
|
||||
self.submat.col(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_col(&mut self, i: uint, col: $tv<N>) {
|
||||
self.submat.set_col(i, col);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! to_homogeneous_impl(
|
||||
($t: ident, $tm: ident) => (
|
||||
impl<N: One + Zero + Clone> ToHomogeneous<$tm<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn to_homogeneous(&self) -> $tm<N> {
|
||||
self.submat.to_homogeneous()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! approx_eq_impl(
|
||||
($t: ident) => (
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon() -> N {
|
||||
// ApproxEq::<N>::approx_epsilon()
|
||||
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &$t<N>) -> bool {
|
||||
self.submat.approx_eq(&other.submat)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||
self.submat.approx_eq_eps(&other.submat, epsilon)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! absolute_impl(
|
||||
($t: ident, $tm: ident) => (
|
||||
impl<N: Signed> Absolute<$tm<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn absolute(&self) -> $tm<N> {
|
||||
self.submat.absolute()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
110
src/structs/spec/complex.rs
Normal file
110
src/structs/spec/complex.rs
Normal file
@ -0,0 +1,110 @@
|
||||
/// Implement nalgebra traits for complex numbers from `extra::complex::Cmplex`.
|
||||
|
||||
use std::num::Zero;
|
||||
use extra::complex::Cmplx;
|
||||
use traits::operations::{Absolute, Inv};
|
||||
use traits::structure::{Dim};
|
||||
|
||||
impl<N: Clone + Num> Absolute<Cmplx<N>> for Cmplx<N> {
|
||||
#[inline]
|
||||
fn absolute(&self) -> Cmplx<N> {
|
||||
Cmplx::new(self.re.clone(), self.im.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Clone + Num + NumCast + Zero> Inv for Cmplx<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Cmplx<N>> {
|
||||
if self.is_zero() {
|
||||
None
|
||||
}
|
||||
else {
|
||||
let _1: N = NumCast::from(1.0);
|
||||
let divisor = _1 / (self.re * self.re - self.im * self.im);
|
||||
|
||||
Some(Cmplx::new(self.re * divisor, -self.im * divisor))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
if self.is_zero() {
|
||||
false
|
||||
}
|
||||
else {
|
||||
let _1: N = NumCast::from(1.0);
|
||||
let divisor = _1 / (self.re * self.re - self.im * self.im);
|
||||
|
||||
self.re = self.re * divisor;
|
||||
self.im = -self.im * divisor;
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Dim for Cmplx<N> {
|
||||
#[inline]
|
||||
fn dim(unsused_self: Option<Cmplx<N>>) -> uint {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Rotation<Vec2<N>> for Cmplx<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec2<N> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec2<N> {
|
||||
-self.rotation();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotate_by(&mut self, rotation: &Vec2<N>) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rotated(&self, rotation: &Vec2<N>) -> Cmplx<N> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, rotation: Vec2<N>) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Rotate<Vec2<N>> for Cmplx<N> {
|
||||
#[inline]
|
||||
fn rotate(&self, rotation: &V) -> V {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotate(&self, rotation: &V) -> V {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> RotationMatrix<Vec2<N>, Vec2<N>, Rotmat<Mat2<N>>> for Cmplx<N> {
|
||||
#[inline]
|
||||
fn to_rot_mat(&self) -> Rotmat<Mat2<N>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Norm<N> for Cmplx<N> {
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalized(&self) -> Self {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&mut self) -> N {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> AbsoluteRotate<V> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&elf, v: &V) -> V {
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use std::num::{One, Zero};
|
||||
use mat;
|
||||
use structs::mat;
|
||||
use traits::operations::{Inv, Transpose};
|
||||
use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform};
|
||||
|
||||
@ -11,11 +11,11 @@ impl One for mat::Identity {
|
||||
}
|
||||
|
||||
impl Inv for mat::Identity {
|
||||
fn inverse(&self) -> Option<mat::Identity> {
|
||||
fn inverted(&self) -> Option<mat::Identity> {
|
||||
Some(mat::Identity::new())
|
||||
}
|
||||
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
use std::num::{Zero, One};
|
||||
use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
|
||||
use mat::{Mat1, Mat2, Mat3, Inv, Row, Col, Mat3MulRhs, Mat2MulRhs};
|
||||
use mat;
|
||||
use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
|
||||
use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs};
|
||||
use structs::mat;
|
||||
use traits::operations::{Inv};
|
||||
use traits::structure::{Row, Col};
|
||||
|
||||
// some specializations:
|
||||
impl<N: Num + Clone>
|
||||
Inv for Mat1<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Mat1<N>> {
|
||||
fn inverted(&self) -> Option<Mat1<N>> {
|
||||
let mut res : Mat1<N> = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
if res.invert() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
@ -19,7 +21,7 @@ Inv for Mat1<N> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
if self.m11.is_zero() {
|
||||
false
|
||||
}
|
||||
@ -34,10 +36,10 @@ Inv for Mat1<N> {
|
||||
impl<N: Num + Clone>
|
||||
Inv for Mat2<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Mat2<N>> {
|
||||
fn inverted(&self) -> Option<Mat2<N>> {
|
||||
let mut res : Mat2<N> = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
if res.invert() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
@ -46,7 +48,7 @@ Inv for Mat2<N> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
let det = self.m11 * self.m22 - self.m21 * self.m12;
|
||||
|
||||
if det.is_zero() {
|
||||
@ -65,10 +67,10 @@ Inv for Mat2<N> {
|
||||
impl<N: Num + Clone>
|
||||
Inv for Mat3<N> {
|
||||
#[inline]
|
||||
fn inverse(&self) -> Option<Mat3<N>> {
|
||||
fn inverted(&self) -> Option<Mat3<N>> {
|
||||
let mut res = self.clone();
|
||||
|
||||
if res.inplace_inverse() {
|
||||
if res.invert() {
|
||||
Some(res)
|
||||
}
|
||||
else {
|
||||
@ -77,7 +79,7 @@ Inv for Mat3<N> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inplace_inverse(&mut self) -> bool {
|
||||
fn invert(&mut self) -> bool {
|
||||
let minor_m12_m23 = self.m22 * self.m33 - self.m32 * self.m23;
|
||||
let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23;
|
||||
let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22;
|
||||
@ -111,7 +113,7 @@ Inv for Mat3<N> {
|
||||
|
||||
impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
|
||||
#[inline]
|
||||
fn num_rows(&self) -> uint {
|
||||
fn nrows(&self) -> uint {
|
||||
3
|
||||
}
|
||||
|
||||
@ -151,7 +153,7 @@ impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
|
||||
|
||||
impl<N: Clone> Col<Vec3<N>> for Mat3<N> {
|
||||
#[inline]
|
||||
fn num_cols(&self) -> uint {
|
||||
fn ncols(&self) -> uint {
|
||||
3
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::num::{Zero, One};
|
||||
use vec::{Vec1, Vec2, Vec3, Vec4, Norm, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis};
|
||||
use mat::{Mat3, Row};
|
||||
use traits::structure::{VecCast, Row, Basis};
|
||||
use traits::geometry::{Norm, Cross, CrossMatrix, UniformSphereSample};
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
||||
use structs::mat::Mat3;
|
||||
|
||||
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
|
||||
#[inline]
|
||||
@ -39,10 +41,10 @@ impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: iplement this for all other vectors
|
||||
// FIXME: implement this for all other vectors
|
||||
impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
|
||||
#[inline]
|
||||
fn num_rows(&self) -> uint {
|
||||
fn nrows(&self) -> uint {
|
||||
2
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::iter::{Iterator, FromIterator};
|
||||
use std::cmp::ApproxEq;
|
||||
use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim};
|
||||
use traits::geometry::{Translation, Dot, Norm};
|
||||
use vec;
|
||||
use structs::vec;
|
||||
|
||||
impl<N> vec::Vec0<N> {
|
||||
/// Creates a new vector.
|
@ -9,16 +9,9 @@ use std::vec::{VecIterator, VecMutIterator};
|
||||
use std::iter::{Iterator, FromIterator};
|
||||
use std::cmp::ApproxEq;
|
||||
|
||||
use traits::geometry::{Transform, Rotate};
|
||||
|
||||
pub use traits::geometry::{FromHomogeneous, ToHomogeneous, Dot, Norm, Cross, CrossMatrix,
|
||||
Translation, Translate, UniformSphereSample};
|
||||
pub use traits::structure::{VecCast, Vec, VecExt, AlgebraicVec, AlgebraicVecExt, Basis, Dim,
|
||||
Indexable, Iterable, IterableMut};
|
||||
pub use traits::operations::{Outer, ScalarAdd, ScalarSub};
|
||||
|
||||
// structs
|
||||
pub use dvec::DVec;
|
||||
use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm,
|
||||
Translation, Translate};
|
||||
use traits::structure::{VecCast, Basis, Dim, Indexable, Iterable, IterableMut};
|
||||
|
||||
mod metal;
|
||||
mod vec_macros;
|
@ -1,16 +1,14 @@
|
||||
use std::num::{Real, One, abs};
|
||||
use std::rand::random;
|
||||
use std::cmp::ApproxEq;
|
||||
use vec::*;
|
||||
use mat::*;
|
||||
use adaptors::rotmat::Rotmat;
|
||||
use na::*;
|
||||
|
||||
macro_rules! test_inv_mat_impl(
|
||||
($t: ty) => (
|
||||
do 10000.times {
|
||||
let randmat : $t = random();
|
||||
|
||||
assert!((randmat.inverse().unwrap() * randmat).approx_eq(&One::one()));
|
||||
assert!((randmat.inverted().unwrap() * randmat).approx_eq(&One::one()));
|
||||
}
|
||||
);
|
||||
)
|
||||
@ -88,7 +86,7 @@ fn test_inv_mat6() {
|
||||
#[test]
|
||||
fn test_rotation2() {
|
||||
do 10000.times {
|
||||
let randmat: Rotmat<Mat2<f64>> = One::one();
|
||||
let randmat: Rot2<f64> = One::one();
|
||||
let ang = &Vec1::new(abs::<f64>(random()) % Real::pi());
|
||||
|
||||
assert!(randmat.rotated(ang).rotation().approx_eq(ang));
|
||||
@ -105,7 +103,7 @@ fn test_index_mat2() {
|
||||
#[test]
|
||||
fn test_inv_rotation3() {
|
||||
do 10000.times {
|
||||
let randmat: Rotmat<Mat3<f64>> = One::one();
|
||||
let randmat: Rot3<f64> = One::one();
|
||||
let dir: Vec3<f64> = random();
|
||||
let ang = &(dir.normalized() * (abs::<f64>(random()) % Real::pi()));
|
||||
let rot = randmat.rotated(ang);
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::num::{Zero, One};
|
||||
use std::rand::{random};
|
||||
use std::cmp::ApproxEq;
|
||||
use vec::*;
|
||||
use mat::*;
|
||||
use na::*;
|
||||
|
||||
macro_rules! test_iterator_impl(
|
||||
($t: ty, $n: ty) => (
|
||||
|
@ -61,141 +61,6 @@ pub trait Rotate<V> {
|
||||
fn inv_rotate(&self, v: &V) -> V;
|
||||
}
|
||||
|
||||
/// Trait of object which represent a transformation, and to which new transformations can
|
||||
/// be appended.
|
||||
///
|
||||
/// A transformation is assumed to be an isometry without reflexion.
|
||||
pub trait Transformation<M> {
|
||||
/// Gets the transformation of `self`.
|
||||
fn transformation(&self) -> M;
|
||||
|
||||
/// Gets the inverse transformation of `self`.
|
||||
fn inv_transformation(&self) -> M;
|
||||
|
||||
/// In-place version of `transformed`.
|
||||
fn transform_by(&mut self, &M);
|
||||
|
||||
/// Appends a transformation to `self`.
|
||||
fn transformed(&self, &M) -> Self;
|
||||
|
||||
/// Sets the transformation of `self`.
|
||||
fn set_transformation(&mut self, M);
|
||||
}
|
||||
|
||||
/// Trait of objects able to transform other objects.
|
||||
///
|
||||
/// This is typically implemented by matrices which transform vectors.
|
||||
pub trait Transform<V> {
|
||||
/// Applies a transformation to `v`.
|
||||
fn transform(&self, &V) -> V;
|
||||
/// Applies an inverse transformation to `v`.
|
||||
fn inv_transform(&self, &V) -> V;
|
||||
}
|
||||
|
||||
/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
|
||||
/// be implemented by quaternions to convert them to a rotation matrix.
|
||||
pub trait RotationMatrix<LV, AV, R: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
|
||||
/// Gets the rotation matrix represented by `self`.
|
||||
fn to_rot_mat(&self) -> R;
|
||||
}
|
||||
|
||||
/// Traits of objects having a dot product.
|
||||
pub trait Dot<N> {
|
||||
/// Computes the dot (inner) product of two vectors.
|
||||
#[inline]
|
||||
fn dot(&self, &Self) -> N;
|
||||
|
||||
/**
|
||||
* Short-cut to compute the projection of a point on a vector, but without
|
||||
* computing intermediate vectors.
|
||||
* The following equation must be verified:
|
||||
*
|
||||
* ~~~{.rust}
|
||||
* a.sub_dot(b, c) == (a - b).dot(c)
|
||||
* ~~~
|
||||
*
|
||||
*/
|
||||
#[inline]
|
||||
fn sub_dot(&self, b: &Self, c: &Self) -> N;
|
||||
}
|
||||
|
||||
/// Traits of objects having an euclidian norm.
|
||||
pub trait Norm<N: Algebraic> {
|
||||
/// Computes the norm of `self`.
|
||||
#[inline]
|
||||
fn norm(&self) -> N {
|
||||
self.sqnorm().sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared norm of `self`.
|
||||
///
|
||||
/// This is usually faster than computing the norm itself.
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N;
|
||||
|
||||
/// Gets the normalized version of `self`.
|
||||
#[inline]
|
||||
fn normalized(&self) -> Self;
|
||||
|
||||
/// In-place version of `normalized`.
|
||||
#[inline]
|
||||
fn normalize(&mut self) -> N;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trait of elements having a cross product.
|
||||
*/
|
||||
pub trait Cross<V> {
|
||||
/// Computes the cross product between two elements (usually vectors).
|
||||
fn cross(&self, other: &Self) -> V;
|
||||
}
|
||||
|
||||
/// Traits of objects which can be put in homogeneous coordinates form.
|
||||
pub trait ToHomogeneous<U> {
|
||||
/// Gets the homogeneous coordinates form of this object.
|
||||
fn to_homogeneous(&self) -> U;
|
||||
}
|
||||
|
||||
/// Traits of objects which can be build from an homogeneous coordinate form.
|
||||
pub trait FromHomogeneous<U> {
|
||||
/// Builds an object from its homogeneous coordinate form.
|
||||
///
|
||||
/// Note that this this is not required that `from` is the inverse of `to_homogeneous`.
|
||||
/// Typically, `from` will remove some informations unrecoverable by `to_homogeneous`.
|
||||
fn from(&U) -> Self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trait of elements having a cross product operation which can be expressed as a matrix.
|
||||
*/
|
||||
pub trait CrossMatrix<M> {
|
||||
/// The matrix associated to any cross product with this vector. I.e. `v.cross(anything)` =
|
||||
/// `v.cross_matrix().rmul(anything)`.
|
||||
fn cross_matrix(&self) -> M;
|
||||
}
|
||||
|
||||
/// Composition of a rotation and an absolute value.
|
||||
///
|
||||
/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but
|
||||
/// doing so is not easy in generic code as it can be a cause of type over-parametrization.
|
||||
pub trait AbsoluteRotate<V> {
|
||||
/// This is the same as:
|
||||
///
|
||||
/// ~~~{.rust}
|
||||
/// self.rotation_matrix().absolute().rmul(v)
|
||||
/// ~~~
|
||||
fn absolute_rotate(&self, v: &V) -> V;
|
||||
}
|
||||
|
||||
/// Trait of vectors able to sample a unit sphere.
|
||||
///
|
||||
/// The number of sample must be sufficient to approximate a sphere using a support mapping
|
||||
/// function.
|
||||
pub trait UniformSphereSample {
|
||||
/// Iterate through the samples.
|
||||
fn sample(&fn(Self));
|
||||
}
|
||||
|
||||
/// Various composition of rotation and translation.
|
||||
///
|
||||
/// Utilities to make rotations with regard to a point different than the origin. All those
|
||||
@ -261,3 +126,138 @@ pub trait RotationWithTranslation<LV: Neg<LV>, AV>: Rotation<AV> + Translation<L
|
||||
|
||||
impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation<LV, AV> for M {
|
||||
}
|
||||
|
||||
/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
|
||||
/// be implemented by quaternions to convert them to a rotation matrix.
|
||||
pub trait RotationMatrix<LV, AV, M: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> {
|
||||
/// Gets the rotation matrix represented by `self`.
|
||||
fn to_rot_mat(&self) -> M;
|
||||
}
|
||||
|
||||
/// Composition of a rotation and an absolute value.
|
||||
///
|
||||
/// The operation is accessible using the `RotationMatrix`, `Absolute`, and `RMul` traits, but
|
||||
/// doing so is not easy in generic code as it can be a cause of type over-parametrization.
|
||||
pub trait AbsoluteRotate<V> {
|
||||
/// This is the same as:
|
||||
///
|
||||
/// ~~~{.rust}
|
||||
/// self.rotation_matrix().absolute().rmul(v)
|
||||
/// ~~~
|
||||
fn absolute_rotate(&self, v: &V) -> V;
|
||||
}
|
||||
|
||||
/// Trait of object which represent a transformation, and to which new transformations can
|
||||
/// be appended.
|
||||
///
|
||||
/// A transformation is assumed to be an isometry without reflexion.
|
||||
pub trait Transformation<M> {
|
||||
/// Gets the transformation of `self`.
|
||||
fn transformation(&self) -> M;
|
||||
|
||||
/// Gets the inverse transformation of `self`.
|
||||
fn inv_transformation(&self) -> M;
|
||||
|
||||
/// In-place version of `transformed`.
|
||||
fn transform_by(&mut self, &M);
|
||||
|
||||
/// Appends a transformation to `self`.
|
||||
fn transformed(&self, &M) -> Self;
|
||||
|
||||
/// Sets the transformation of `self`.
|
||||
fn set_transformation(&mut self, M);
|
||||
}
|
||||
|
||||
/// Trait of objects able to transform other objects.
|
||||
///
|
||||
/// This is typically implemented by matrices which transform vectors.
|
||||
pub trait Transform<V> {
|
||||
/// Applies a transformation to `v`.
|
||||
fn transform(&self, &V) -> V;
|
||||
/// Applies an inverse transformation to `v`.
|
||||
fn inv_transform(&self, &V) -> V;
|
||||
}
|
||||
|
||||
/// Traits of objects having a dot product.
|
||||
pub trait Dot<N> {
|
||||
/// Computes the dot (inner) product of two vectors.
|
||||
#[inline]
|
||||
fn dot(&self, &Self) -> N;
|
||||
|
||||
/**
|
||||
* Short-cut to compute the projection of a point on a vector, but without
|
||||
* computing intermediate vectors.
|
||||
* The following equation must be verified:
|
||||
*
|
||||
* ~~~{.rust}
|
||||
* a.sub_dot(b, c) == (a - b).dot(c)
|
||||
* ~~~
|
||||
*
|
||||
*/
|
||||
#[inline]
|
||||
fn sub_dot(&self, b: &Self, c: &Self) -> N;
|
||||
}
|
||||
|
||||
/// Traits of objects having an euclidian norm.
|
||||
pub trait Norm<N: Algebraic> {
|
||||
/// Computes the norm of `self`.
|
||||
#[inline]
|
||||
fn norm(&self) -> N {
|
||||
self.sqnorm().sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared norm of `self`.
|
||||
///
|
||||
/// This is usually faster than computing the norm itself.
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N;
|
||||
|
||||
/// Gets the normalized version of `self`.
|
||||
#[inline]
|
||||
fn normalized(&self) -> Self;
|
||||
|
||||
/// In-place version of `normalized`.
|
||||
#[inline]
|
||||
fn normalize(&mut self) -> N;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trait of elements having a cross product.
|
||||
*/
|
||||
pub trait Cross<V> {
|
||||
/// Computes the cross product between two elements (usually vectors).
|
||||
fn cross(&self, other: &Self) -> V;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trait of elements having a cross product operation which can be expressed as a matrix.
|
||||
*/
|
||||
pub trait CrossMatrix<M> {
|
||||
/// The matrix associated to any cross product with this vector. I.e. `v.cross(anything)` =
|
||||
/// `v.cross_matrix().rmul(anything)`.
|
||||
fn cross_matrix(&self) -> M;
|
||||
}
|
||||
|
||||
/// Traits of objects which can be put in homogeneous coordinates form.
|
||||
pub trait ToHomogeneous<U> {
|
||||
/// Gets the homogeneous coordinates form of this object.
|
||||
fn to_homogeneous(&self) -> U;
|
||||
}
|
||||
|
||||
/// Traits of objects which can be build from an homogeneous coordinate form.
|
||||
pub trait FromHomogeneous<U> {
|
||||
/// Builds an object from its homogeneous coordinate form.
|
||||
///
|
||||
/// Note that this this is not required that `from` is the inverse of `to_homogeneous`.
|
||||
/// Typically, `from` will remove some informations unrecoverable by `to_homogeneous`.
|
||||
fn from(&U) -> Self;
|
||||
}
|
||||
|
||||
/// Trait of vectors able to sample a unit sphere.
|
||||
///
|
||||
/// The number of sample must be sufficient to approximate a sphere using a support mapping
|
||||
/// function.
|
||||
pub trait UniformSphereSample {
|
||||
/// Iterate through the samples.
|
||||
fn sample(&fn(Self));
|
||||
}
|
||||
|
15
src/traits/mod.rs
Normal file
15
src/traits/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! Mathematical traits.
|
||||
|
||||
pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Rotate,
|
||||
Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
|
||||
Transform, Transformation, Translate, Translation, UniformSphereSample};
|
||||
|
||||
pub use self::structure::{AlgebraicVec, AlgebraicVecExt, Basis, Col, Dim, Indexable, Iterable,
|
||||
IterableMut, Mat, MatCast, Row, Vec, VecCast, VecExt};
|
||||
|
||||
pub use self::operations::{Absolute, Cov, Inv, LMul, Mean, Outer, RMul, ScalarAdd, ScalarSub,
|
||||
Transpose};
|
||||
|
||||
pub mod geometry;
|
||||
pub mod structure;
|
||||
pub mod operations;
|
@ -12,9 +12,9 @@ pub trait Absolute<A> {
|
||||
/// Trait of objects having an inverse. Typically used to implement matrix inverse.
|
||||
pub trait Inv {
|
||||
/// Returns the inverse of `self`.
|
||||
fn inverse(&self) -> Option<Self>;
|
||||
fn inverted(&self) -> Option<Self>;
|
||||
/// In-place version of `inverse`.
|
||||
fn inplace_inverse(&mut self) -> bool;
|
||||
fn invert(&mut self) -> bool;
|
||||
}
|
||||
|
||||
/// Trait of objects which can be transposed.
|
||||
@ -27,9 +27,9 @@ pub trait Transpose {
|
||||
}
|
||||
|
||||
/// Traits of objects having an outer product.
|
||||
pub trait Outer<V, M> {
|
||||
pub trait Outer<M> {
|
||||
/// Computes the outer product: `self * other`
|
||||
fn outer(&self, other: &V) -> M;
|
||||
fn outer(&self, other: &Self) -> M;
|
||||
}
|
||||
|
||||
/// Trait for computing the covariance of a set of data.
|
||||
|
@ -70,38 +70,12 @@ pub trait Basis {
|
||||
|
||||
/// Iterates through a basis of the subspace orthogonal to `self`.
|
||||
fn orthonormal_subspace_basis(&self, &fn(Self) -> bool);
|
||||
|
||||
/// Creates the canonical basis of the space in which this object lives.
|
||||
fn canonical_basis_list() -> ~[Self] {
|
||||
let mut res = ~[];
|
||||
|
||||
do Basis::canonical_basis |elem| {
|
||||
res.push(elem);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Creates a basis of the subspace orthogonal to `self`.
|
||||
fn orthonormal_subspace_basis_list(&self) -> ~[Self] {
|
||||
let mut res = ~[];
|
||||
|
||||
do self.orthonormal_subspace_basis |elem| {
|
||||
res.push(elem);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to access rows of a matrix or a vector.
|
||||
pub trait Row<R> {
|
||||
/// The number of column of `self`.
|
||||
fn num_rows(&self) -> uint;
|
||||
fn nrows(&self) -> uint;
|
||||
/// Reads the `i`-th row of `self`.
|
||||
fn row(&self, i: uint) -> R;
|
||||
/// Writes the `i`-th row of `self`.
|
||||
@ -114,7 +88,7 @@ pub trait Row<R> {
|
||||
/// Trait to access columns of a matrix or vector.
|
||||
pub trait Col<C> {
|
||||
/// The number of column of this matrix or vector.
|
||||
fn num_cols(&self) -> uint;
|
||||
fn ncols(&self) -> uint;
|
||||
|
||||
/// Reads the `i`-th column of `self`.
|
||||
fn col(&self, i: uint) -> C;
|
||||
|
162
src/types.rs
162
src/types.rs
@ -1,162 +0,0 @@
|
||||
//! Useful type aliases.
|
||||
|
||||
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
|
||||
use mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
||||
use adaptors::rotmat::Rotmat;
|
||||
use adaptors::transform::Transform;
|
||||
|
||||
// 1D
|
||||
/// 1-dimensional `f64`-valued vector.
|
||||
pub type Vec1f64 = Vec1<f64>;
|
||||
/// 1-dimensional `f32`-valued vector.
|
||||
pub type Vec1f32 = Vec1<f32>;
|
||||
|
||||
/// 1-dimensional `f64`-valued matrix.
|
||||
pub type Mat1f64 = Mat1<f64>;
|
||||
/// 1-dimensional `f32`-valued matrix.
|
||||
pub type Mat1f32 = Mat1<f32>;
|
||||
|
||||
// /// 1-dimensional `f64`-valued rotation matrix.
|
||||
// pub type Rot1f64 = Rotmat<Mat1<f64>>;
|
||||
// /// 1-dimensional `f32`-valued rotation matrix.
|
||||
// pub type Rot1f32 = Rotmat<Mat1<f32>>;
|
||||
//
|
||||
// /// 1-dimensional `f64`-valued isometric transform.
|
||||
// pub type Iso1f64 = Transform<Rot1f64, Vec1f64>;
|
||||
// /// 1-dimensional `f32`-valued isometric transform.
|
||||
// pub type Iso1f32 = Transform<Rot1f32, Vec1f32>;
|
||||
|
||||
/// 1-dimensional `f64`-valued general transform.
|
||||
pub type Aff1f64 = Transform<Vec1f64, Mat1f64>;
|
||||
/// 1-dimensional `f32`-valued general transform.
|
||||
pub type Aff1f32 = Transform<Vec1f32, Mat1f32>;
|
||||
|
||||
// 2D
|
||||
/// 2-dimensional `f64`-valued vector.
|
||||
pub type Vec2f64 = Vec2<f64>;
|
||||
/// 2-dimensional `f32`-valued vector.
|
||||
pub type Vec2f32 = Vec2<f32>;
|
||||
|
||||
/// 2-dimensional `f64`-valued matrix.
|
||||
pub type Mat2f64 = Mat2<f64>;
|
||||
/// 2-dimensional `f32`-valued matrix.
|
||||
pub type Mat2f32 = Mat2<f32>;
|
||||
|
||||
/// 2-dimensional `f64`-valued rotation matrix.
|
||||
pub type Rot2f64 = Rotmat<Mat2<f64>>;
|
||||
/// 2-dimensional `f32`-valued rotation matrix.
|
||||
pub type Rot2f32 = Rotmat<Mat2<f32>>;
|
||||
|
||||
/// 2-dimensional `f64`-valued isometric transform.
|
||||
pub type Iso2f64 = Transform<Vec2f64, Rot2f64>;
|
||||
/// 2-dimensional `f32`-valued isometric transform.
|
||||
pub type Iso2f32 = Transform<Vec2f32, Rot2f32>;
|
||||
|
||||
/// 2-dimensional `f64`-valued general transform.
|
||||
pub type Aff2f64 = Transform<Vec2f64, Mat2f64>;
|
||||
/// 2-dimensional `f32`-valued general transform.
|
||||
pub type Aff2f32 = Transform<Vec2f32, Mat2f32>;
|
||||
|
||||
// 3D
|
||||
/// 3-dimensional `f64`-valued vector.
|
||||
pub type Vec3f64 = Vec3<f64>;
|
||||
/// 3-dimensional `f32`-valued vector.
|
||||
pub type Vec3f32 = Vec3<f32>;
|
||||
|
||||
/// 3-dimensional `f64`-valued matrix.
|
||||
pub type Mat3f64 = Mat3<f64>;
|
||||
/// 3-dimensional `f32`-valued matrix.
|
||||
pub type Mat3f32 = Mat3<f32>;
|
||||
|
||||
/// 3-dimensional `f64`-valued rotation matrix.
|
||||
pub type Rot3f64 = Rotmat<Mat3<f64>>;
|
||||
/// 3-dimensional `f32`-valued rotation matrix.
|
||||
pub type Rot3f32 = Rotmat<Mat3<f32>>;
|
||||
|
||||
/// 3-dimensional `f64`-valued isometric transform.
|
||||
pub type Iso3f64 = Transform<Vec3f64, Rot3f64>;
|
||||
/// 3-dimensional `f32`-valued isometric transform.
|
||||
pub type Iso3f32 = Transform<Vec3f32, Rot3f32>;
|
||||
|
||||
/// 3-dimensional `f64`-valued general transform.
|
||||
pub type Aff3f64 = Transform<Vec3f64, Mat3f64>;
|
||||
/// 3-dimensional `f32`-valued general transform.
|
||||
pub type Aff3f32 = Transform<Vec3f32, Mat3f32>;
|
||||
|
||||
// 4D
|
||||
/// 4-dimensional `f64`-valued vector.
|
||||
pub type Vec4f64 = Vec4<f64>;
|
||||
/// 4-dimensional `f32`-valued vector.
|
||||
pub type Vec4f32 = Vec4<f32>;
|
||||
|
||||
/// 4-dimensional `f64`-valued matrix.
|
||||
pub type Mat4f64 = Mat4<f64>;
|
||||
/// 4-dimensional `f32`-valued matrix.
|
||||
pub type Mat4f32 = Mat4<f32>;
|
||||
|
||||
/// 4-dimensional `f64`-valued rotation matrix.
|
||||
pub type Rot4f64 = Rotmat<Mat4<f64>>;
|
||||
/// 4-dimensional `f32`-valued rotation matrix.
|
||||
pub type Rot4f32 = Rotmat<Mat4<f32>>;
|
||||
|
||||
/// 4-dimensional `f64`-valued isometric transform.
|
||||
pub type Iso4f64 = Transform<Vec4f64, Mat4f64>;
|
||||
/// 4-dimensional `f32`-valued isometric transform.
|
||||
pub type Iso4f32 = Transform<Vec4f32, Mat4f32>;
|
||||
|
||||
/// 4-dimensional `f64`-valued general transform.
|
||||
pub type Aff4f64 = Transform<Vec4f64, Mat4f64>;
|
||||
/// 4-dimensional `f32`-valued general transform.
|
||||
pub type Aff4f32 = Transform<Vec4f32, Mat4f32>;
|
||||
|
||||
// 5D
|
||||
/// 5-dimensional `f64`-valued vector.
|
||||
pub type Vec5f64 = Vec5<f64>;
|
||||
/// 5-dimensional `f32`-valued vector.
|
||||
pub type Vec5f32 = Vec5<f32>;
|
||||
|
||||
/// 5-dimensional `f64`-valued matrix.
|
||||
pub type Mat5f64 = Mat5<f64>;
|
||||
/// 5-dimensional `f32`-valued matrix.
|
||||
pub type Mat5f32 = Mat5<f32>;
|
||||
|
||||
// /// 5-dimensional `f64`-valued rotation matrix.
|
||||
// pub type Rot5f64 = Rotmat<Mat5<f64>>;
|
||||
// /// 5-dimensional `f32`-valued rotation matrix.
|
||||
// pub type Rot5f32 = Rotmat<Mat5<f32>>;
|
||||
//
|
||||
// /// 5-dimensional `f64`-valued isometric transform.
|
||||
// pub type Iso5f64 = Transform<Rot5f64, Vec5f64>;
|
||||
// /// 5-dimensional `f32`-valued isometric transform.
|
||||
// pub type Iso5f32 = Transform<Rot5f32, Vec5f32>;
|
||||
|
||||
/// 5-dimensional `f64`-valued general transform.
|
||||
pub type Aff5f64 = Transform<Vec5f64, Mat5f64>;
|
||||
/// 5-dimensional `f32`-valued general transform.
|
||||
pub type Aff5f32 = Transform<Vec5f32, Mat5f32>;
|
||||
|
||||
// 6D
|
||||
/// 6-dimensional `f64`-valued vector.
|
||||
pub type Vec6f64 = Vec6<f64>;
|
||||
/// 6-dimensional `f32`-valued vector.
|
||||
pub type Vec6f32 = Vec6<f32>;
|
||||
|
||||
/// 6-dimensional `f64`-valued matrix.
|
||||
pub type Mat6f64 = Mat6<f64>;
|
||||
/// 6-dimensional `f32`-valued matrix.
|
||||
pub type Mat6f32 = Mat6<f32>;
|
||||
|
||||
// /// 6-dimensional `f64`-valued rotation matrix.
|
||||
// pub type Rot6f64 = Rotmat<Mat6<f64>>;
|
||||
// /// 6-dimensional `f32`-valued rotation matrix.
|
||||
// pub type Rot6f32 = Rotmat<Mat6<f32>>;
|
||||
//
|
||||
// /// 6-dimensional `f64`-valued isometric transform.
|
||||
// pub type Iso6f64 = Transform<Rot6f64, Vec6f64>;
|
||||
// /// 6-dimensional `f32`-valued isometric transform.
|
||||
// pub type Iso6f32 = Transform<Rot6f32, Vec6f32>;
|
||||
|
||||
/// 6-dimensional `f64`-valued general transform.
|
||||
pub type Aff6f64 = Transform<Vec6f64, Mat6f64>;
|
||||
/// 6-dimensional `f32`-valued general transform.
|
||||
pub type Aff6f32 = Transform<Vec6f32, Mat6f32>;
|
Loading…
Reference in New Issue
Block a user