forked from M-Labs/nalgebra
Merge pull request #175 from sebcrozet/sim_and_vecn
Release v0.6.0: similarity transformations, VecN, and computer-graphics fixes.
This commit is contained in:
commit
b910ce914f
32
CHANGELOG
Normal file
32
CHANGELOG
Normal file
@ -0,0 +1,32 @@
|
||||
# Change Log
|
||||
All notable changes to `nalgebra`, starting with the version 0.6.0 will be
|
||||
documented here.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [0.6.0]
|
||||
**Announcement:** a users forum has been created for `nalgebra`, `ncollide`, and `nphysics`. See
|
||||
you [there](http://users.nphysics.org)!
|
||||
|
||||
### Added
|
||||
* Added a dependency to [generic-array](https://crates.io/crates/generic-array). Feature-gated:
|
||||
requires `features="generic_sizes"`.
|
||||
* Added statically sized vectors with user-defined sizes: `VecN`. Feature-gated: requires
|
||||
`features="generic_sizes"`.
|
||||
* Added similarity transformations (an uniform scale followed by a rotation followed by a
|
||||
translation): `Sim2`, `Sim3`.
|
||||
|
||||
### Removed
|
||||
* Removed zero-sized elements `Vec0`, `Pnt0`.
|
||||
* Removed 4-dimensional transformations `Rot4` and `Iso4` (which had an implementation to incomplete to be useful).
|
||||
|
||||
### Modified
|
||||
* Vectors are now multipliable with isometries. This will result into a pure rotation (this is how
|
||||
vectors differ from point semantically: they design directions so they are not translatable).
|
||||
* `{Iso3, Rot3}::look_at` reimplemented and renamed to `::look_at_rh` and `::look_at_lh` to agree
|
||||
with the computer graphics community (in particular, the GLM library). Use the `::look_at_rh`
|
||||
variant to build a view matrix that
|
||||
may be successfully used with `Persp` and `Ortho`.
|
||||
* The old `{Iso3, Rot3}::look_at` implementations are now called `::new_observer_frame`.
|
||||
* Rename every `fov` on `Persp` to `fovy`.
|
||||
* Fixed the perspective and orthographic projection matrices.
|
17
Cargo.toml
17
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nalgebra"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
authors = [ "Sébastien Crozet <developer@crozet.re>" ] # FIXME: add the contributors.
|
||||
|
||||
description = "Linear algebra library for computer physics, computer graphics and general low-dimensional linear algebra for Rust."
|
||||
@ -17,13 +17,22 @@ path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
# Generate arbitrary instances of nalgebra types for testing with quickcheck
|
||||
arbitrary = ["quickcheck"]
|
||||
arbitrary = [ "quickcheck" ]
|
||||
generic_sizes = [ "generic-array", "typenum" ]
|
||||
|
||||
[dependencies]
|
||||
rustc-serialize = "0.3.*"
|
||||
rand = "0.3.*"
|
||||
num = "0.1.*"
|
||||
num = "0.1.*"
|
||||
|
||||
[dependencies.generic-array]
|
||||
optional = true
|
||||
version = "0.2.*"
|
||||
|
||||
[dependencies.typenum]
|
||||
optional = true
|
||||
version = "1.3.*"
|
||||
|
||||
[dependencies.quickcheck]
|
||||
optional = true
|
||||
version = "0.2.*"
|
||||
version = "0.2.*"
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
tmp=_git_distcheck
|
||||
|
||||
all:
|
||||
cargo build --release
|
||||
cargo build --release --features arbitrary
|
||||
|
||||
test:
|
||||
cargo test
|
||||
|
26
README.md
26
README.md
@ -9,12 +9,12 @@ nalgebra
|
||||
* real time computer graphics.
|
||||
* real time computer physics.
|
||||
|
||||
An on-line version of this documentation is available [here](http://nalgebra.org).
|
||||
An on-line version of this documentation is available [here](http://nalgebra.org/doc/nalgebra).
|
||||
|
||||
## Using **nalgebra**
|
||||
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`.
|
||||
This module re-exports everything and includes free functions for all traits methods doing
|
||||
out-of-place modifications.
|
||||
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`. This
|
||||
module re-exports everything and includes free functions for all traits methods performing
|
||||
out-of-place operations.
|
||||
|
||||
* You can import the whole prelude using:
|
||||
|
||||
@ -44,15 +44,17 @@ fn main() {
|
||||
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
||||
an optimized set of tools for computer graphics and physics. Those features include:
|
||||
|
||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||
* Vectors with predefined static sizes: `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||
* Vector with a user-defined static size: `VecN` (available only with the `generic_sizes` feature).
|
||||
* Points with static sizes: `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||
* Rotation matrices: `Rot2`, `Rot3`
|
||||
* Quaternions: `Quat`, `UnitQuat`.
|
||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
||||
* Isometries (translation ⨯ rotation): `Iso2`, `Iso3`
|
||||
* Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Sim2`, `Sim3`.
|
||||
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
||||
* Dynamically sized vector: `DVec`.
|
||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
||||
* A few methods for data analysis: `Cov`, `Mean`.
|
||||
* Dynamically sized heap-allocated vector: `DVec`.
|
||||
* Dynamically sized stack-allocated vectors with a maximum size: `DVec1` to `DVec6`.
|
||||
* Dynamically sized heap-allocated (square or rectangular) matrix: `DMat`.
|
||||
* Linear algebra and data analysis operators: `Cov`, `Mean`, `qr`, `cholesky`.
|
||||
* Almost one trait per functionality: useful for generic programming.
|
||||
* Operator overloading using multidispatch.
|
||||
|
@ -1,5 +1,8 @@
|
||||
#![feature(test)]
|
||||
|
||||
#[cfg(feature = "generic_sizes")]
|
||||
extern crate typenum;
|
||||
|
||||
extern crate test;
|
||||
extern crate rand;
|
||||
extern crate nalgebra as na;
|
||||
@ -57,3 +60,53 @@ bench_unop!(_bench_vec4_norm, Vec4<f32>, norm);
|
||||
bench_unop!(_bench_vec2_normalize, Vec2<f32>, normalize);
|
||||
bench_unop!(_bench_vec3_normalize, Vec3<f32>, normalize);
|
||||
bench_unop!(_bench_vec4_normalize, Vec4<f32>, normalize);
|
||||
|
||||
#[cfg(feature = "generic_sizes")]
|
||||
mod bench_vecn {
|
||||
use typenum::{U2, U3, U4};
|
||||
use na::VecN;
|
||||
|
||||
bench_binop!(_bench_vecn2_add_v, VecN<f32, U2>, VecN<f32, U2>, add);
|
||||
bench_binop!(_bench_vecn3_add_v, VecN<f32, U3>, VecN<f32, U3>, add);
|
||||
bench_binop!(_bench_vecn4_add_v, VecN<f32, U4>, VecN<f32, U4>, add);
|
||||
|
||||
bench_binop!(_bench_vecn2_sub_v, VecN<f32, U2>, VecN<f32, U2>, sub);
|
||||
bench_binop!(_bench_vecn3_sub_v, VecN<f32, U3>, VecN<f32, U3>, sub);
|
||||
bench_binop!(_bench_vecn4_sub_v, VecN<f32, U4>, VecN<f32, U4>, sub);
|
||||
|
||||
bench_binop!(_bench_vecn2_mul_v, VecN<f32, U2>, VecN<f32, U2>, mul);
|
||||
bench_binop!(_bench_vecn3_mul_v, VecN<f32, U3>, VecN<f32, U3>, mul);
|
||||
bench_binop!(_bench_vecn4_mul_v, VecN<f32, U4>, VecN<f32, U4>, mul);
|
||||
|
||||
bench_binop!(_bench_vecn2_div_v, VecN<f32, U2>, VecN<f32, U2>, div);
|
||||
bench_binop!(_bench_vecn3_div_v, VecN<f32, U3>, VecN<f32, U3>, div);
|
||||
bench_binop!(_bench_vecn4_div_v, VecN<f32, U4>, VecN<f32, U4>, div);
|
||||
|
||||
bench_binop!(_bench_vecn2_add_s, VecN<f32, U2>, f32, add);
|
||||
bench_binop!(_bench_vecn3_add_s, VecN<f32, U3>, f32, add);
|
||||
bench_binop!(_bench_vecn4_add_s, VecN<f32, U4>, f32, add);
|
||||
|
||||
bench_binop!(_bench_vecn2_sub_s, VecN<f32, U2>, f32, sub);
|
||||
bench_binop!(_bench_vecn3_sub_s, VecN<f32, U3>, f32, sub);
|
||||
bench_binop!(_bench_vecn4_sub_s, VecN<f32, U4>, f32, sub);
|
||||
|
||||
bench_binop!(_bench_vecn2_mul_s, VecN<f32, U2>, f32, mul);
|
||||
bench_binop!(_bench_vecn3_mul_s, VecN<f32, U3>, f32, mul);
|
||||
bench_binop!(_bench_vecn4_mul_s, VecN<f32, U4>, f32, mul);
|
||||
|
||||
bench_binop!(_bench_vecn2_div_s, VecN<f32, U2>, f32, div);
|
||||
bench_binop!(_bench_vecn3_div_s, VecN<f32, U3>, f32, div);
|
||||
bench_binop!(_bench_vecn4_div_s, VecN<f32, U4>, f32, div);
|
||||
|
||||
bench_binop_na!(_bench_vecn2_dot, VecN<f32, U2>, VecN<f32, U2>, dot);
|
||||
bench_binop_na!(_bench_vecn3_dot, VecN<f32, U3>, VecN<f32, U3>, dot);
|
||||
bench_binop_na!(_bench_vecn4_dot, VecN<f32, U4>, VecN<f32, U4>, dot);
|
||||
|
||||
bench_unop!(_bench_vecn2_norm, VecN<f32, U2>, norm);
|
||||
bench_unop!(_bench_vecn3_norm, VecN<f32, U3>, norm);
|
||||
bench_unop!(_bench_vecn4_norm, VecN<f32, U4>, norm);
|
||||
|
||||
bench_unop!(_bench_vecn2_normalize, VecN<f32, U2>, normalize);
|
||||
bench_unop!(_bench_vecn3_normalize, VecN<f32, U3>, normalize);
|
||||
bench_unop!(_bench_vecn4_normalize, VecN<f32, U4>, normalize);
|
||||
}
|
||||
|
43
src/lib.rs
43
src/lib.rs
@ -3,16 +3,16 @@
|
||||
|
||||
**nalgebra** is a low-dimensional linear algebra library written for Rust targeting:
|
||||
|
||||
* general-purpose linear algebra (still lacks a lot of features…).
|
||||
* low-dimensional general-purpose linear algebra (still lacks a lot of features…).
|
||||
* real time computer graphics.
|
||||
* real time computer physics.
|
||||
|
||||
An on-line version of this documentation is available [here](http://nalgebra.org).
|
||||
An on-line version of this documentation is available [here](http://nalgebra.org/doc/nalgebra).
|
||||
|
||||
## Using **nalgebra**
|
||||
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`.
|
||||
This module re-exports everything and includes free functions for all traits methods doing
|
||||
out-of-place modifications.
|
||||
All the functionality of **nalgebra** is grouped in one place: the root module `nalgebra::`. This
|
||||
module re-exports everything and includes free functions for all traits methods performing
|
||||
out-of-place operations.
|
||||
|
||||
* You can import the whole prelude using:
|
||||
|
||||
@ -41,18 +41,20 @@ fn main() {
|
||||
**nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with
|
||||
an optimized set of tools for computer graphics and physics. Those features include:
|
||||
|
||||
* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||
* Points with static sizes: `Pnt0`, `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||
* Vectors with predefined static sizes: `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
|
||||
* Vector with a user-defined static size: `VecN` (available only with the `generic_sizes` feature).
|
||||
* Points with static sizes: `Pnt1`, `Pnt2`, `Pnt3`, `Pnt4`, `Pnt5`, `Pnt6`.
|
||||
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
|
||||
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
|
||||
* Rotation matrices: `Rot2`, `Rot3`
|
||||
* Quaternions: `Quat`, `UnitQuat`.
|
||||
* Isometries: `Iso2`, `Iso3`, `Iso4`.
|
||||
* Isometries (translation ⨯ rotation): `Iso2`, `Iso3`
|
||||
* Similarity transformations (translation ⨯ rotation ⨯ uniform scale): `Sim2`, `Sim3`.
|
||||
* 3D projections for computer graphics: `Persp3`, `PerspMat3`, `Ortho3`, `OrthoMat3`.
|
||||
* Dynamically sized vector: `DVec`.
|
||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
||||
* A few methods for data analysis: `Cov`, `Mean`.
|
||||
* Dynamically sized heap-allocated vector: `DVec`.
|
||||
* Dynamically sized stack-allocated vectors with a maximum size: `DVec1` to `DVec6`.
|
||||
* Dynamically sized heap-allocated (square or rectangular) matrix: `DMat`.
|
||||
* Linear algebra and data analysis operators: `Cov`, `Mean`, `qr`, `cholesky`.
|
||||
* Almost one trait per functionality: useful for generic programming.
|
||||
* Operator overloading using multidispatch.
|
||||
|
||||
|
||||
## **nalgebra** in use
|
||||
@ -77,6 +79,9 @@ extern crate rustc_serialize;
|
||||
extern crate rand;
|
||||
extern crate num;
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
extern crate generic_array;
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
extern crate quickcheck;
|
||||
|
||||
@ -133,16 +138,20 @@ pub use traits::{
|
||||
UniformSphereSample
|
||||
};
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
pub use structs::VecN;
|
||||
|
||||
pub use structs::{
|
||||
Identity,
|
||||
DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6,
|
||||
DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6,
|
||||
Iso2, Iso3, Iso4,
|
||||
Iso2, Iso3,
|
||||
Sim2, Sim3,
|
||||
Mat1, Mat2, Mat3, Mat4,
|
||||
Mat5, Mat6,
|
||||
Rot2, Rot3, Rot4,
|
||||
Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6,
|
||||
Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6,
|
||||
Rot2, Rot3,
|
||||
Vec1, Vec2, Vec3, Vec4, Vec5, Vec6,
|
||||
Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6,
|
||||
Persp3, PerspMat3,
|
||||
Ortho3, OrthoMat3,
|
||||
Quat, UnitQuat
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! Matrix with dimensions unknown at compile-time.
|
||||
|
||||
#![allow(missing_docs)] // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
|
||||
use std::cmp;
|
||||
use std::mem;
|
||||
use std::iter::repeat;
|
||||
@ -110,7 +108,7 @@ impl<N: Clone + Copy> DMat<N> {
|
||||
}
|
||||
|
||||
impl<N> DMat<N> {
|
||||
/// Builds a matrix using an initialization function.
|
||||
/// Builds a matrix filled with the results of a function applied to each of its component coordinates.
|
||||
#[inline(always)]
|
||||
pub fn from_fn<F: FnMut(usize, usize) -> N>(nrows: usize, ncols: usize, mut f: F) -> DMat<N> {
|
||||
DMat {
|
||||
@ -131,6 +129,7 @@ impl<N> DMat<N> {
|
||||
dmat_impl!(DMat, DVec);
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized matrix with at most one row and column.
|
||||
pub struct DMat1<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
@ -141,6 +140,7 @@ small_dmat_impl!(DMat1, DVec1, 1, 0);
|
||||
small_dmat_from_impl!(DMat1, 1, ::zero());
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized square or rectangular matrix with at most 2 rows and columns.
|
||||
pub struct DMat2<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
@ -153,6 +153,7 @@ small_dmat_from_impl!(DMat2, 2, ::zero(), ::zero(),
|
||||
::zero(), ::zero());
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized square or rectangular matrix with at most 3 rows and columns.
|
||||
pub struct DMat3<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
@ -167,6 +168,7 @@ small_dmat_from_impl!(DMat3, 3, ::zero(), ::zero(), ::zero(),
|
||||
::zero(), ::zero(), ::zero());
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized square or rectangular matrix with at most 4 rows and columns.
|
||||
pub struct DMat4<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
@ -183,6 +185,7 @@ small_dmat_from_impl!(DMat4, 4, ::zero(), ::zero(), ::zero(), ::zero(),
|
||||
::zero(), ::zero(), ::zero(), ::zero());
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized square or rectangular matrix with at most 5 rows and columns.
|
||||
pub struct DMat5<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
@ -201,6 +204,7 @@ small_dmat_from_impl!(DMat5, 5, ::zero(), ::zero(), ::zero(), ::zero(), ::zero()
|
||||
::zero(), ::zero(), ::zero(), ::zero(), ::zero());
|
||||
|
||||
|
||||
/// A stack-allocated dynamically sized square or rectangular matrix with at most 6 rows and columns.
|
||||
pub struct DMat6<N> {
|
||||
nrows: usize,
|
||||
ncols: usize,
|
||||
|
@ -19,6 +19,7 @@ macro_rules! dmat_impl(
|
||||
self.mij.iter().all(|e| e.is_zero())
|
||||
}
|
||||
|
||||
/// Set this matrix components to zero.
|
||||
#[inline]
|
||||
pub fn reset(&mut self) {
|
||||
for mij in self.mij.iter_mut() {
|
||||
@ -881,7 +882,8 @@ macro_rules! small_dmat_from_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> $dmat<N> {
|
||||
impl<N: Copy> $dmat<N> {
|
||||
/// Creates a new matrix with uninitialized components (with `mem::uninitialized()`).
|
||||
#[inline]
|
||||
pub unsafe fn new_uninitialized(nrows: usize, ncols: usize) -> $dmat<N> {
|
||||
assert!(nrows <= $dim);
|
||||
|
@ -1,7 +1,5 @@
|
||||
//! Vector with dimensions unknown at compile-time.
|
||||
|
||||
#![allow(missing_docs)] // we hide doc to not have to document the $trhs double dispatch trait.
|
||||
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
use std::iter::repeat;
|
||||
@ -56,12 +54,13 @@ impl<N: Clone> DVec<N> {
|
||||
}
|
||||
|
||||
impl<N> DVec<N> {
|
||||
/// Builds a vector filled with the result of a function.
|
||||
/// Builds a vector filled with the results of a function applied to each of its component coordinates.
|
||||
#[inline(always)]
|
||||
pub fn from_fn<F: FnMut(usize) -> N>(dim: usize, mut f: F) -> DVec<N> {
|
||||
DVec { at: (0..dim).map(|i| f(i)).collect() }
|
||||
}
|
||||
|
||||
/// The vector length.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.at.len()
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
macro_rules! dvec_impl(
|
||||
($dvec: ident) => (
|
||||
vecn_dvec_common_impl!($dvec);
|
||||
|
||||
impl<N: Zero + Copy + Clone> $dvec<N> {
|
||||
/// Builds a vector filled with zeros.
|
||||
///
|
||||
@ -11,68 +13,6 @@ macro_rules! dvec_impl(
|
||||
pub fn new_zeros(dim: usize) -> $dvec<N> {
|
||||
$dvec::from_elem(dim, ::zero())
|
||||
}
|
||||
|
||||
/// Tests if all components of the vector are zeroes.
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.as_ref().iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> $dvec<N> {
|
||||
/// Slices this vector.
|
||||
#[inline]
|
||||
pub fn as_ref<'a>(&'a self) -> &'a [N] {
|
||||
&self.at[.. self.len()]
|
||||
}
|
||||
|
||||
/// Mutably slices this vector.
|
||||
#[inline]
|
||||
pub fn as_mut<'a>(&'a mut self) -> &'a mut [N] {
|
||||
let len = self.len();
|
||||
&mut self.at[.. len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Shape<usize> for $dvec<N> {
|
||||
#[inline]
|
||||
fn shape(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy> Indexable<usize, N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn swap(&mut self, i: usize, j: usize) {
|
||||
assert!(i < self.len());
|
||||
assert!(j < self.len());
|
||||
self.as_mut().swap(i, j);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, i: usize) -> N {
|
||||
*self.at[..].get_unchecked(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, i: usize, val: N) {
|
||||
*self.at[..].get_unchecked_mut(i) = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<N, T> Index<T> for $dvec<N> where [N]: Index<T> {
|
||||
type Output = <[N] as Index<T>>::Output;
|
||||
|
||||
fn index(&self, i: T) -> &<[N] as Index<T>>::Output {
|
||||
&self.as_ref()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T> IndexMut<T> for $dvec<N> where [N]: IndexMut<T> {
|
||||
fn index_mut(&mut self, i: T) -> &mut <[N] as Index<T>>::Output {
|
||||
&mut self.as_mut()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: One + Zero + Copy + Clone> $dvec<N> {
|
||||
@ -94,33 +34,6 @@ macro_rules! dvec_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Iterable<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N> {
|
||||
self.as_ref().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> IterableMut<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
|
||||
self.as_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Mul<N, Output = N>> Axpy<N> for $dvec<N> {
|
||||
fn axpy(&mut self, a: &N, x: &$dvec<N>) {
|
||||
assert!(self.len() == x.len());
|
||||
|
||||
for i in 0..x.len() {
|
||||
unsafe {
|
||||
let self_i = self.unsafe_at(i);
|
||||
self.unsafe_set(i, self_i + *a * x.unsafe_at(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + ApproxEq<N>> $dvec<N> {
|
||||
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
|
||||
/// vectors, mutually orthogonal, with all its component equal to 0.0 except one which is equal
|
||||
@ -128,7 +41,7 @@ macro_rules! dvec_impl(
|
||||
pub fn canonical_basis_with_dim(dim: usize) -> Vec<$dvec<N>> {
|
||||
let mut res : Vec<$dvec<N>> = Vec::new();
|
||||
|
||||
for i in 0..dim {
|
||||
for i in 0 .. dim {
|
||||
let mut basis_element : $dvec<N> = $dvec::new_zeros(dim);
|
||||
|
||||
basis_element[i] = ::one();
|
||||
@ -147,7 +60,7 @@ macro_rules! dvec_impl(
|
||||
let dim = self.len();
|
||||
let mut res : Vec<$dvec<N>> = Vec::new();
|
||||
|
||||
for i in 0..dim {
|
||||
for i in 0 .. dim {
|
||||
let mut basis_element : $dvec<N> = $dvec::new_zeros(self.len());
|
||||
|
||||
basis_element[i] = ::one();
|
||||
@ -175,217 +88,13 @@ macro_rules! dvec_impl(
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero> Mul<$dvec<N>> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $dvec<N>) -> $dvec<N> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left * *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Div<N, Output = N> + Zero> Div<$dvec<N>> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: $dvec<N>) -> $dvec<N> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left / *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Zero> Add<$dvec<N>> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $dvec<N>) -> $dvec<N> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left + *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Sub<N, Output = N> + Zero> Sub<$dvec<N>> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $dvec<N>) -> $dvec<N> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left - *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<Output = N> + Zero + Copy> Neg for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> $dvec<N> {
|
||||
FromIterator::from_iter(self.as_ref().iter().map(|a| -*a))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Dot<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn dot(&self, other: &$dvec<N>) -> N {
|
||||
assert!(self.len() == other.len());
|
||||
let mut res: N = ::zero();
|
||||
for i in 0..self.len() {
|
||||
res = res + unsafe { self.unsafe_at(i) * other.unsafe_at(i) };
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Norm<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N {
|
||||
Dot::dot(self, self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&self) -> $dvec<N> {
|
||||
let mut res : $dvec<N> = self.clone();
|
||||
let _ = res.normalize_mut();
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_mut(&mut self) -> N {
|
||||
let l = Norm::norm(self);
|
||||
|
||||
for n in self.as_mut().iter_mut() {
|
||||
*n = *n / l;
|
||||
}
|
||||
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Cast<f64>> Mean<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn mean(&self) -> N {
|
||||
let normalizer = ::cast(1.0f64 / self.len() as f64);
|
||||
self.iter().fold(::zero(), |acc, x| acc + *x * normalizer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $dvec<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$dvec<N>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_ulps(_: Option<$dvec<N>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$dvec<N>, epsilon: &N) -> bool {
|
||||
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &$dvec<N>, ulps: u32) -> bool {
|
||||
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero> Mul<N> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: N) -> $dvec<N> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e * right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Div<N, Output = N> + Zero> Div<N> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: N) -> $dvec<N> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e / right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Zero> Add<N> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: N) -> $dvec<N> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e + right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Sub<N, Output = N> + Zero> Sub<N> for $dvec<N> {
|
||||
type Output = $dvec<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: N) -> $dvec<N> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e - right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! small_dvec_impl (
|
||||
($dvec: ident, $dim: expr, $($idx: expr),*) => (
|
||||
dvec_impl!($dvec);
|
||||
|
||||
impl<N> $dvec<N> {
|
||||
/// The number of elements of this vector.
|
||||
#[inline]
|
||||
@ -434,8 +143,6 @@ macro_rules! small_dvec_impl (
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dvec_impl!($dvec);
|
||||
)
|
||||
);
|
||||
|
||||
@ -490,7 +197,7 @@ macro_rules! small_dvec_from_impl (
|
||||
|
||||
let mut at: [N; $dim] = [ $( $zeros, )* ];
|
||||
|
||||
for i in 0..dim {
|
||||
for i in 0 .. dim {
|
||||
at[i] = f(i);
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,25 @@
|
||||
//! Isometric transformations.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Sub, Mul, Neg};
|
||||
|
||||
use rand::{Rand, Rng};
|
||||
use num::One;
|
||||
use structs::mat::{Mat3, Mat4, Mat5};
|
||||
use structs::mat::{Mat3, Mat4};
|
||||
use traits::structure::{Cast, Dim, Col, BaseFloat, BaseNum};
|
||||
use traits::operations::{Inv, ApproxEq};
|
||||
use traits::geometry::{RotationMatrix, Rotation, Rotate, AbsoluteRotate, Transform, Transformation,
|
||||
Translate, Translation, ToHomogeneous};
|
||||
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
||||
use structs::pnt::{Pnt2, Pnt3, Pnt4};
|
||||
use structs::rot::{Rot2, Rot3, Rot4};
|
||||
use structs::vec::{Vec1, Vec2, Vec3};
|
||||
use structs::pnt::{Pnt2, Pnt3};
|
||||
use structs::rot::{Rot2, Rot3};
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
|
||||
/// Two dimensional isometry.
|
||||
/// Two dimensional **direct** isometry.
|
||||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// This is the composition of a rotation followed by a translation. Vectors `Vec2` are not
|
||||
/// affected by the translational component of this transformation while points `Pnt2` are.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
@ -33,9 +30,10 @@ pub struct Iso2<N> {
|
||||
pub translation: Vec2<N>
|
||||
}
|
||||
|
||||
/// Three dimensional isometry.
|
||||
/// Three dimensional **direct** isometry.
|
||||
///
|
||||
/// This is the composition of a rotation followed by a translation.
|
||||
/// This is the composition of a rotation followed by a translation. Vectors `Vec3` are not
|
||||
/// affected by the translational component of this transformation while points `Pnt3` are.
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
@ -46,56 +44,58 @@ pub struct Iso3<N> {
|
||||
pub translation: Vec3<N>
|
||||
}
|
||||
|
||||
/// Four dimensional isometry.
|
||||
///
|
||||
/// Isometries conserve angles and distances, hence do not allow shearing nor scaling.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct Iso4<N> {
|
||||
/// The rotation applicable by this isometry.
|
||||
pub rotation: Rot4<N>,
|
||||
/// The translation applicable by this isometry.
|
||||
pub translation: Vec4<N>
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat> Iso3<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.
|
||||
/// Creates an isometry that corresponds to the local frame of an observer standing at the
|
||||
/// point `eye` and looking toward `target`.
|
||||
///
|
||||
/// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
|
||||
/// `eye`.
|
||||
///
|
||||
/// # 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(eye: &Pnt3<N>, at: &Pnt3<N>, up: &Vec3<N>) -> Iso3<N> {
|
||||
Iso3::new_with_rotmat(eye.as_vec().clone(), Rot3::look_at(&(*at - *eye), up))
|
||||
}
|
||||
|
||||
/// 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(eye: &Pnt3<N>, at: &Pnt3<N>, up: &Vec3<N>) -> Iso3<N> {
|
||||
Iso3::new_with_rotmat(eye.as_vec().clone(), Rot3::look_at_z(&(*at - *eye), up))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Iso4<N> {
|
||||
// XXX remove that when iso_impl works for Iso4
|
||||
/// Creates a new isometry from a rotation matrix and a vector.
|
||||
/// * eye - The observer position.
|
||||
/// * target - The target position.
|
||||
/// * up - Vertical direction. The only requirement of this parameter is to not be collinear
|
||||
/// to `eye - at`. Non-collinearity is not checked.
|
||||
#[inline]
|
||||
pub fn new_with_rotmat(translation: Vec4<N>, rotation: Rot4<N>) -> Iso4<N> {
|
||||
Iso4 {
|
||||
rotation: rotation,
|
||||
translation: translation
|
||||
}
|
||||
pub fn new_observer_frame(eye: &Pnt3<N>, target: &Pnt3<N>, up: &Vec3<N>) -> Iso3<N> {
|
||||
let new_rotmat = Rot3::new_observer_frame(&(*target - *eye), up);
|
||||
Iso3::new_with_rotmat(eye.as_vec().clone(), new_rotmat)
|
||||
}
|
||||
|
||||
/// Builds a right-handed look-at view matrix.
|
||||
///
|
||||
/// This conforms to the common notion of right handed look-at matrix from the computer
|
||||
/// graphics community.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * eye - The eye position.
|
||||
/// * target - The target position.
|
||||
/// * up - A vector approximately aligned with required the vertical axis. The only
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_rh(eye: &Pnt3<N>, target: &Pnt3<N>, up: &Vec3<N>) -> Iso3<N> {
|
||||
let rot = Rot3::look_at_rh(&(*target - *eye), up);
|
||||
let trans = rot * (-*eye);
|
||||
|
||||
Iso3::new_with_rotmat(trans.to_vec(), rot)
|
||||
}
|
||||
|
||||
/// Builds a left-handed look-at view matrix.
|
||||
///
|
||||
/// This conforms to the common notion of left handed look-at matrix from the computer
|
||||
/// graphics community.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * eye - The eye position.
|
||||
/// * target - The target position.
|
||||
/// * up - A vector approximately aligned with required the vertical axis. The only
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_lh(eye: &Pnt3<N>, target: &Pnt3<N>, up: &Vec3<N>) -> Iso3<N> {
|
||||
let rot = Rot3::look_at_lh(&(*target - *eye), up);
|
||||
let trans = rot * (-*eye);
|
||||
|
||||
Iso3::new_with_rotmat(trans.to_vec(), rot)
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,9 +115,11 @@ rotate_impl!(Iso2, Vec2);
|
||||
translation_impl!(Iso2, Vec2);
|
||||
translate_impl!(Iso2, Pnt2);
|
||||
iso_mul_iso_impl!(Iso2);
|
||||
iso_mul_rot_impl!(Iso2, Rot2);
|
||||
iso_mul_pnt_impl!(Iso2, Pnt2);
|
||||
pnt_mul_iso_impl!(Iso2, Pnt2);
|
||||
iso_mul_vec_impl!(Iso2, Vec2);
|
||||
arbitrary_iso_impl!(Iso2);
|
||||
iso_display_impl!(Iso2);
|
||||
|
||||
iso_impl!(Iso3, Rot3, Vec3, Vec3);
|
||||
rotation_matrix_impl!(Iso3, Rot3, Vec3, Vec3);
|
||||
@ -135,27 +137,8 @@ rotate_impl!(Iso3, Vec3);
|
||||
translation_impl!(Iso3, Vec3);
|
||||
translate_impl!(Iso3, Pnt3);
|
||||
iso_mul_iso_impl!(Iso3);
|
||||
iso_mul_rot_impl!(Iso3, Rot3);
|
||||
iso_mul_pnt_impl!(Iso3, Pnt3);
|
||||
pnt_mul_iso_impl!(Iso3, Pnt3);
|
||||
iso_mul_vec_impl!(Iso3, Vec3);
|
||||
arbitrary_iso_impl!(Iso3);
|
||||
|
||||
// iso_impl!(Iso4, Rot4, Vec4, Vec4);
|
||||
// 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, Pnt4);
|
||||
transformation_impl!(Iso4);
|
||||
rotate_impl!(Iso4, Vec4);
|
||||
translation_impl!(Iso4, Vec4);
|
||||
translate_impl!(Iso4, Pnt4);
|
||||
iso_mul_iso_impl!(Iso4);
|
||||
iso_mul_pnt_impl!(Iso4, Pnt4);
|
||||
pnt_mul_iso_impl!(Iso4, Pnt4);
|
||||
// FIXME: as soon as Rot4<N>: Arbitrary
|
||||
// arbitrary_iso_impl!(Iso4);
|
||||
iso_display_impl!(Iso3);
|
||||
|
@ -3,7 +3,7 @@
|
||||
macro_rules! iso_impl(
|
||||
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/// Creates a new isometry from a rotation matrix and a vector.
|
||||
/// Creates a new isometry from an axis-angle rotation, and a vector.
|
||||
#[inline]
|
||||
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
|
||||
$t {
|
||||
@ -76,6 +76,30 @@ macro_rules! iso_mul_iso_impl(
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! iso_mul_rot_impl(
|
||||
($t: ident, $tr: ident) => (
|
||||
impl<N: BaseFloat> Mul<$tr<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tr<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(self.translation, self.rotation * right)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $tr<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self * right.translation,
|
||||
self * right.rotation)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! iso_mul_pnt_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
@ -86,16 +110,20 @@ macro_rules! iso_mul_pnt_impl(
|
||||
self.rotation * right + self.translation
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: there is no viable pre-multiplication definition because of the translation
|
||||
// component.
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pnt_mul_iso_impl(
|
||||
macro_rules! iso_mul_vec_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$t<N>> for $tv<N> {
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $tv<N> {
|
||||
(self + right.translation) * right.rotation
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
self.rotation * right
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -378,3 +406,26 @@ macro_rules! arbitrary_iso_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! iso_display_impl(
|
||||
($t: ident) => (
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "Isometry {{"));
|
||||
|
||||
if let Some(precision) = f.precision() {
|
||||
try!(writeln!(f, "... translation: {:.*}", precision, self.translation));
|
||||
try!(writeln!(f, "... rotation matrix:"));
|
||||
try!(write!(f, "{:.*}", precision, *self.rotation.submat()));
|
||||
}
|
||||
else {
|
||||
try!(writeln!(f, "... translation: {}", self.translation));
|
||||
try!(writeln!(f, "... rotation matrix:"));
|
||||
try!(write!(f, "{}", *self.rotation.submat()));
|
||||
}
|
||||
|
||||
writeln!(f, "}}")
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#![allow(missing_docs)] // we allow missing to avoid having to document the mij components.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Sub, Mul, Div, Index, IndexMut};
|
||||
use std::mem;
|
||||
use std::slice::{Iter, IterMut};
|
||||
@ -82,6 +83,7 @@ eigen_qr_impl!(Mat1, Vec1);
|
||||
arbitrary_impl!(Mat1, m11);
|
||||
rand_impl!(Mat1, m11);
|
||||
mean_impl!(Mat1, Vec1, 1);
|
||||
mat_display_impl!(Mat1, 1);
|
||||
|
||||
/// Square matrix of dimension 2.
|
||||
#[repr(C)]
|
||||
@ -136,6 +138,7 @@ eigen_qr_impl!(Mat2, Vec2);
|
||||
arbitrary_impl!(Mat2, m11, m12, m21, m22);
|
||||
rand_impl!(Mat2, m11, m12, m21, m22);
|
||||
mean_impl!(Mat2, Vec2, 2);
|
||||
mat_display_impl!(Mat2, 2);
|
||||
|
||||
/// Square matrix of dimension 3.
|
||||
#[repr(C)]
|
||||
@ -233,6 +236,7 @@ rand_impl!(Mat3,
|
||||
m31, m32, m33
|
||||
);
|
||||
mean_impl!(Mat3, Vec3, 3);
|
||||
mat_display_impl!(Mat3, 3);
|
||||
|
||||
/// Square matrix of dimension 4.
|
||||
#[repr(C)]
|
||||
@ -353,6 +357,7 @@ rand_impl!(Mat4,
|
||||
m41, m42, m43, m44
|
||||
);
|
||||
mean_impl!(Mat4, Vec4, 4);
|
||||
mat_display_impl!(Mat4, 4);
|
||||
|
||||
/// Square matrix of dimension 5.
|
||||
#[repr(C)]
|
||||
@ -490,6 +495,7 @@ rand_impl!(Mat5,
|
||||
m51, m52, m53, m54, m55
|
||||
);
|
||||
mean_impl!(Mat5, Vec5, 5);
|
||||
mat_display_impl!(Mat5, 5);
|
||||
|
||||
/// Square matrix of dimension 6.
|
||||
#[repr(C)]
|
||||
@ -632,3 +638,4 @@ rand_impl!(Mat6,
|
||||
m61, m62, m63, m64, m65, m66
|
||||
);
|
||||
mean_impl!(Mat6, Vec6, 6);
|
||||
mat_display_impl!(Mat6, 6);
|
||||
|
@ -749,3 +749,56 @@ macro_rules! mean_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! mat_display_impl(
|
||||
($t: ident, $dim: expr) => (
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
// XXX: will will not always work correctly due to rounding errors.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn integral_length<N: BaseFloat>(val: &N) -> usize {
|
||||
let mut res = 1;
|
||||
let mut curr: N = ::cast(10.0f64);
|
||||
|
||||
while curr <= *val {
|
||||
curr = curr * ::cast(10.0f64);
|
||||
res = res + 1;
|
||||
}
|
||||
|
||||
if val.is_sign_negative() {
|
||||
res + 1
|
||||
}
|
||||
else {
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
let mut max_decimal_length = 0;
|
||||
let mut decimal_lengths: $t<usize> = ::zero();
|
||||
for i in 0 .. $dim {
|
||||
for j in 0 .. $dim {
|
||||
decimal_lengths[(i, j)] = integral_length(&self[(i, j)].clone());
|
||||
max_decimal_length = ::max(max_decimal_length, decimal_lengths[(i, j)]);
|
||||
}
|
||||
}
|
||||
|
||||
let precision = f.precision().unwrap_or(3);
|
||||
let max_number_length = max_decimal_length + precision + 1;
|
||||
|
||||
try!(writeln!(f, " ┌ {:>width$} ┐", "", width = max_number_length * $dim + $dim - 1));
|
||||
|
||||
for i in 0 .. $dim {
|
||||
try!(write!(f, " │"));
|
||||
for j in 0 .. $dim {
|
||||
let number_length = decimal_lengths[(i, j)] + precision + 1;
|
||||
let pad = max_number_length - number_length;
|
||||
try!(write!(f, " {:>thepad$}", "", thepad = pad));
|
||||
try!(write!(f, "{:.*}", precision, (*self)[(i, j)]));
|
||||
}
|
||||
try!(writeln!(f, " │"));
|
||||
}
|
||||
|
||||
writeln!(f, " └ {:>width$} ┘", "", width = max_number_length * $dim + $dim - 1)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -2,17 +2,24 @@
|
||||
|
||||
pub use self::dmat::{DMat, DMat1, DMat2, DMat3, DMat4, DMat5, DMat6};
|
||||
pub use self::dvec::{DVec, DVec1, DVec2, DVec3, DVec4, DVec5, DVec6};
|
||||
pub use self::vec::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
|
||||
pub use self::pnt::{Pnt0, Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
|
||||
pub use self::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
|
||||
pub use self::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
|
||||
pub use self::mat::{Identity, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
|
||||
pub use self::rot::{Rot2, Rot3, Rot4};
|
||||
pub use self::iso::{Iso2, Iso3, Iso4};
|
||||
pub use self::rot::{Rot2, Rot3};
|
||||
pub use self::iso::{Iso2, Iso3};
|
||||
pub use self::sim::{Sim2, Sim3};
|
||||
pub use self::persp::{Persp3, PerspMat3};
|
||||
pub use self::ortho::{Ortho3, OrthoMat3};
|
||||
pub use self::quat::{Quat, UnitQuat};
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
pub use self::vecn::VecN;
|
||||
|
||||
mod dmat_macros;
|
||||
mod dmat;
|
||||
mod vecn_macros;
|
||||
#[cfg(feature="generic_sizes")]
|
||||
mod vecn;
|
||||
mod dvec_macros;
|
||||
mod dvec;
|
||||
mod vec_macros;
|
||||
@ -26,15 +33,16 @@ mod rot_macros;
|
||||
mod rot;
|
||||
mod iso_macros;
|
||||
mod iso;
|
||||
mod sim_macros;
|
||||
mod sim;
|
||||
mod persp;
|
||||
mod ortho;
|
||||
|
||||
// specialization for some 1d, 2d and 3d operations
|
||||
// Specialization for some 1d, 2d and 3d operations.
|
||||
#[doc(hidden)]
|
||||
mod spec {
|
||||
mod identity;
|
||||
mod mat;
|
||||
mod vec0;
|
||||
mod vec;
|
||||
mod primitives;
|
||||
// mod complex;
|
||||
|
@ -7,18 +7,24 @@ use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
/// A 3D orthographic projection stored without any matrix.
|
||||
///
|
||||
/// Reading or modifying its individual properties is cheap but applying the transformation is costly.
|
||||
/// This flips the `z` axis and maps a axis-aligned cube to the unit cube with corners varying from
|
||||
/// `(-1, -1, -1)` to `(1, 1, 1)`. Reading or modifying its individual properties is cheap but
|
||||
/// applying the transformation is costly.
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct Ortho3<N> {
|
||||
width: N,
|
||||
height: N,
|
||||
left: N,
|
||||
right: N,
|
||||
bottom: N,
|
||||
top: N,
|
||||
znear: N,
|
||||
zfar: N
|
||||
}
|
||||
|
||||
/// A 3D orthographic projection stored as a 4D matrix.
|
||||
///
|
||||
/// Reading or modifying its individual properties is costly but applying the transformation is cheap.
|
||||
/// This flips the `z` axis and maps a axis-aligned cube to the unit cube with corners varying from
|
||||
/// `(-1, -1, -1)` to `(1, 1, 1)`. Reading or modifying its individual properties is costly but
|
||||
/// applying the transformation is cheap.
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct OrthoMat3<N> {
|
||||
mat: Mat4<N>
|
||||
@ -26,14 +32,16 @@ pub struct OrthoMat3<N> {
|
||||
|
||||
impl<N: BaseFloat> Ortho3<N> {
|
||||
/// Creates a new 3D orthographic projection.
|
||||
pub fn new(width: N, height: N, znear: N, zfar: N) -> Ortho3<N> {
|
||||
pub fn new(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> Ortho3<N> {
|
||||
assert!(!::is_zero(&(zfar - znear)));
|
||||
assert!(!::is_zero(&width));
|
||||
assert!(!::is_zero(&height));
|
||||
assert!(!::is_zero(&(left - right)));
|
||||
assert!(!::is_zero(&(top - bottom)));
|
||||
|
||||
Ortho3 {
|
||||
width: width,
|
||||
height: height,
|
||||
left: left,
|
||||
right: right,
|
||||
bottom: bottom,
|
||||
top: top,
|
||||
znear: znear,
|
||||
zfar: zfar
|
||||
}
|
||||
@ -46,32 +54,46 @@ impl<N: BaseFloat> Ortho3<N> {
|
||||
|
||||
/// Build a `OrthoMat3` representing this projection.
|
||||
pub fn to_persp_mat(&self) -> OrthoMat3<N> {
|
||||
OrthoMat3::new(self.width, self.height, self.znear, self.zfar)
|
||||
OrthoMat3::new(self.left, self.right, self.bottom, self.top, self.znear, self.zfar)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for Ortho3<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Ortho3<N> {
|
||||
let width = reject(g, |x| !::is_zero(x));
|
||||
let height = reject(g, |x| !::is_zero(x));
|
||||
let znear = Arbitrary::arbitrary(g);
|
||||
let zfar = reject(g, |&x: &N| !::is_zero(&(x - znear)));
|
||||
Ortho3::new(width, height, znear, zfar)
|
||||
let left = Arbitrary::arbitrary(g);
|
||||
let right = reject(g, |x: &N| *x > left);
|
||||
let bottom = Arbitrary::arbitrary(g);
|
||||
let top = reject(g, |x: &N| *x > bottom);
|
||||
let znear = Arbitrary::arbitrary(g);
|
||||
let zfar = reject(g, |x: &N| *x > znear);
|
||||
Ortho3::new(left, right, bottom, top, znear, zfar)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone> Ortho3<N> {
|
||||
/// The width of the view cuboid.
|
||||
/// The smallest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn width(&self) -> N {
|
||||
self.width.clone()
|
||||
pub fn left(&self) -> N {
|
||||
self.left.clone()
|
||||
}
|
||||
|
||||
/// The height of the view cuboid.
|
||||
/// The largest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn height(&self) -> N {
|
||||
self.height.clone()
|
||||
pub fn right(&self) -> N {
|
||||
self.right.clone()
|
||||
}
|
||||
|
||||
/// The smallest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn bottom(&self) -> N {
|
||||
self.bottom.clone()
|
||||
}
|
||||
|
||||
/// The largest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn top(&self) -> N {
|
||||
self.top.clone()
|
||||
}
|
||||
|
||||
/// The near plane offset of the view cuboid.
|
||||
@ -86,27 +108,45 @@ impl<N: BaseFloat + Clone> Ortho3<N> {
|
||||
self.zfar.clone()
|
||||
}
|
||||
|
||||
/// Sets the width of the view cuboid.
|
||||
/// Sets the smallest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_width(&mut self, width: N) {
|
||||
self.width = width
|
||||
pub fn set_left(&mut self, left: N) {
|
||||
assert!(left < self.right, "The left corner must be farther than the right corner.");
|
||||
self.left = left
|
||||
}
|
||||
|
||||
/// Sets the height of the view cuboid.
|
||||
/// Sets the largest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_height(&mut self, height: N) {
|
||||
self.height = height
|
||||
pub fn set_right(&mut self, right: N) {
|
||||
assert!(right > self.left, "The left corner must be farther than the right corner.");
|
||||
self.right = right
|
||||
}
|
||||
|
||||
/// Sets the smallest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_bottom(&mut self, bottom: N) {
|
||||
assert!(bottom < self.top, "The top corner must be higher than the bottom corner.");
|
||||
self.bottom = bottom
|
||||
}
|
||||
|
||||
/// Sets the largest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_top(&mut self, top: N) {
|
||||
assert!(top > self.bottom, "The top corner must be higher than the left corner.");
|
||||
self.top = top
|
||||
}
|
||||
|
||||
/// Sets the near plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_znear(&mut self, znear: N) {
|
||||
assert!(znear < self.zfar, "The far plane must be farther than the near plane.");
|
||||
self.znear = znear
|
||||
}
|
||||
|
||||
/// Sets the far plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_zfar(&mut self, zfar: N) {
|
||||
assert!(zfar > self.znear, "The far plane must be farther than the near plane.");
|
||||
self.zfar = zfar
|
||||
}
|
||||
|
||||
@ -126,22 +166,35 @@ impl<N: BaseFloat + Clone> Ortho3<N> {
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> OrthoMat3<N> {
|
||||
/// Creates a new orthographic projection matrix from the width, heihgt, znear and zfar planes of the view cuboid.
|
||||
pub fn new(width: N, height: N, znear: N, zfar: N) -> OrthoMat3<N> {
|
||||
assert!(!::is_zero(&(zfar - znear)));
|
||||
assert!(!::is_zero(&width));
|
||||
assert!(!::is_zero(&height));
|
||||
/// Creates a new orthographic projection matrix.
|
||||
pub fn new(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> OrthoMat3<N> {
|
||||
assert!(left < right, "The left corner must be farther than the right corner.");
|
||||
assert!(bottom < top, "The top corner must be higher than the bottom corner.");
|
||||
assert!(znear < zfar, "The far plane must be farther than the near plane.");
|
||||
|
||||
let mat: Mat4<N> = ::one();
|
||||
|
||||
let mut res = OrthoMat3 { mat: mat };
|
||||
res.set_width(width);
|
||||
res.set_height(height);
|
||||
res.set_left_and_right(left, right);
|
||||
res.set_bottom_and_top(bottom, top);
|
||||
res.set_znear_and_zfar(znear, zfar);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Creates a new orthographic projection matrix from an aspect ratio and the vertical field of view.
|
||||
pub fn new_with_fov(aspect: N, vfov: N, znear: N, zfar: N) -> OrthoMat3<N> {
|
||||
assert!(znear < zfar, "The far plane must be farther than the near plane.");
|
||||
assert!(!::is_zero(&aspect));
|
||||
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let width = zfar * (vfov / _2).tan();
|
||||
let height = width / aspect;
|
||||
|
||||
OrthoMat3::new(-width / _2, width / _2, -height / _2, height / _2, znear, zfar)
|
||||
}
|
||||
|
||||
/// Creates a new orthographic matrix from a 4D matrix.
|
||||
///
|
||||
/// This is unsafe because the input matrix is not checked to be a orthographic projection.
|
||||
@ -158,42 +211,68 @@ impl<N: BaseFloat> OrthoMat3<N> {
|
||||
&self.mat
|
||||
}
|
||||
|
||||
/// The width of the view cuboid.
|
||||
/// The smallest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn width(&self) -> N {
|
||||
<N as Cast<f64>>::from(2.0) / self.mat.m11
|
||||
pub fn left(&self) -> N {
|
||||
(-::one::<N>() - self.mat.m14) / self.mat.m11
|
||||
}
|
||||
|
||||
/// The height of the view cuboid.
|
||||
/// The largest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn height(&self) -> N {
|
||||
<N as Cast<f64>>::from(2.0) / self.mat.m22
|
||||
pub fn right(&self) -> N {
|
||||
(::one::<N>() - self.mat.m14) / self.mat.m11
|
||||
}
|
||||
|
||||
/// The smallest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn bottom(&self) -> N {
|
||||
(-::one::<N>() - self.mat.m24) / self.mat.m22
|
||||
}
|
||||
|
||||
/// The largest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn top(&self) -> N {
|
||||
(::one::<N>() - self.mat.m24) / self.mat.m22
|
||||
}
|
||||
|
||||
/// The near plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn znear(&self) -> N {
|
||||
(self.mat.m34 + ::one()) / self.mat.m33
|
||||
(::one::<N>() + self.mat.m34) / self.mat.m33
|
||||
}
|
||||
|
||||
/// The far plane offset of the view cuboid.
|
||||
#[inline]
|
||||
pub fn zfar(&self) -> N {
|
||||
(self.mat.m34 - ::one()) / self.mat.m33
|
||||
(-::one::<N>() + self.mat.m34) / self.mat.m33
|
||||
}
|
||||
|
||||
/// Sets the width of the view cuboid.
|
||||
/// Sets the smallest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_width(&mut self, width: N) {
|
||||
assert!(!::is_zero(&width));
|
||||
self.mat.m11 = <N as Cast<f64>>::from(2.0) / width;
|
||||
pub fn set_left(&mut self, left: N) {
|
||||
let right = self.right();
|
||||
self.set_left_and_right(left, right);
|
||||
}
|
||||
|
||||
/// Sets the height of the view cuboid.
|
||||
/// Sets the largest x-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_height(&mut self, height: N) {
|
||||
assert!(!::is_zero(&height));
|
||||
self.mat.m22 = <N as Cast<f64>>::from(2.0) / height;
|
||||
pub fn set_right(&mut self, right: N) {
|
||||
let left = self.left();
|
||||
self.set_left_and_right(left, right);
|
||||
}
|
||||
|
||||
/// Sets the smallest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_bottom(&mut self, bottom: N) {
|
||||
let top = self.top();
|
||||
self.set_bottom_and_top(bottom, top);
|
||||
}
|
||||
|
||||
/// Sets the largest y-coordinate of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_top(&mut self, top: N) {
|
||||
let bottom = self.bottom();
|
||||
self.set_bottom_and_top(bottom, top);
|
||||
}
|
||||
|
||||
/// Sets the near plane offset of the view cuboid.
|
||||
@ -210,6 +289,22 @@ impl<N: BaseFloat> OrthoMat3<N> {
|
||||
self.set_znear_and_zfar(znear, zfar);
|
||||
}
|
||||
|
||||
/// Sets the view cuboid coordinates along the `x` axis.
|
||||
#[inline]
|
||||
pub fn set_left_and_right(&mut self, left: N, right: N) {
|
||||
assert!(left < right, "The left corner must be farther than the right corner.");
|
||||
self.mat.m11 = <N as Cast<f64>>::from(2.0) / (right - left);
|
||||
self.mat.m14 = -(right + left) / (right - left);
|
||||
}
|
||||
|
||||
/// Sets the view cuboid coordinates along the `y` axis.
|
||||
#[inline]
|
||||
pub fn set_bottom_and_top(&mut self, bottom: N, top: N) {
|
||||
assert!(bottom < top, "The top corner must be higher than the bottom corner.");
|
||||
self.mat.m22 = <N as Cast<f64>>::from(2.0) / (top - bottom);
|
||||
self.mat.m24 = -(top + bottom) / (top - bottom);
|
||||
}
|
||||
|
||||
/// Sets the near and far plane offsets of the view cuboid.
|
||||
#[inline]
|
||||
pub fn set_znear_and_zfar(&mut self, znear: N, zfar: N) {
|
||||
@ -222,8 +317,8 @@ impl<N: BaseFloat> OrthoMat3<N> {
|
||||
#[inline]
|
||||
pub fn project_pnt(&self, p: &Pnt3<N>) -> Pnt3<N> {
|
||||
Pnt3::new(
|
||||
self.mat.m11 * p.x,
|
||||
self.mat.m22 * p.y,
|
||||
self.mat.m11 * p.x + self.mat.m14,
|
||||
self.mat.m22 * p.y + self.mat.m24,
|
||||
self.mat.m33 * p.z + self.mat.m34
|
||||
)
|
||||
}
|
||||
|
@ -7,18 +7,22 @@ use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
/// A 3D perspective projection stored without any matrix.
|
||||
///
|
||||
/// Reading or modifying its individual properties is cheap but applying the transformation is costly.
|
||||
/// This maps a frustrum cube to the unit cube with corners varying from `(-1, -1, -1)` to
|
||||
/// `(1, 1, 1)`. Reading or modifying its individual properties is cheap but applying the
|
||||
/// transformation is costly.
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct Persp3<N> {
|
||||
aspect: N,
|
||||
fov: N,
|
||||
fovy: N,
|
||||
znear: N,
|
||||
zfar: N
|
||||
}
|
||||
|
||||
/// A 3D perspective projection stored as a 4D matrix.
|
||||
///
|
||||
/// Reading or modifying its individual properties is costly but applying the transformation is cheap.
|
||||
/// This maps a frustrum to the unit cube with corners varying from `(-1, -1, -1)` to
|
||||
/// `(1, 1, 1)`. Reading or modifying its individual properties is costly but applying the
|
||||
/// transformation is cheap.
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct PerspMat3<N> {
|
||||
mat: Mat4<N>
|
||||
@ -26,13 +30,13 @@ pub struct PerspMat3<N> {
|
||||
|
||||
impl<N: BaseFloat> Persp3<N> {
|
||||
/// Creates a new 3D perspective projection.
|
||||
pub fn new(aspect: N, fov: N, znear: N, zfar: N) -> Persp3<N> {
|
||||
pub fn new(aspect: N, fovy: N, znear: N, zfar: N) -> Persp3<N> {
|
||||
assert!(!::is_zero(&(zfar - znear)));
|
||||
assert!(!::is_zero(&aspect));
|
||||
|
||||
Persp3 {
|
||||
aspect: aspect,
|
||||
fov: fov,
|
||||
fovy: fovy,
|
||||
znear: znear,
|
||||
zfar: zfar
|
||||
}
|
||||
@ -45,7 +49,7 @@ impl<N: BaseFloat> Persp3<N> {
|
||||
|
||||
/// Build a `PerspMat3` representing this projection.
|
||||
pub fn to_persp_mat(&self) -> PerspMat3<N> {
|
||||
PerspMat3::new(self.aspect, self.fov, self.znear, self.zfar)
|
||||
PerspMat3::new(self.aspect, self.fovy, self.znear, self.zfar)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,10 +70,10 @@ impl<N: BaseFloat + Clone> Persp3<N> {
|
||||
self.aspect.clone()
|
||||
}
|
||||
|
||||
/// Gets the field of view of the view frustrum.
|
||||
/// Gets the y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn fov(&self) -> N {
|
||||
self.fov.clone()
|
||||
pub fn fovy(&self) -> N {
|
||||
self.fovy.clone()
|
||||
}
|
||||
|
||||
/// Gets the near plane offset of the view frustrum.
|
||||
@ -92,12 +96,12 @@ impl<N: BaseFloat + Clone> Persp3<N> {
|
||||
self.aspect = aspect;
|
||||
}
|
||||
|
||||
/// Sets the field of view of the view frustrum.
|
||||
/// Sets the y field of view of the view frustrum.
|
||||
///
|
||||
/// This method does not build any matrix.
|
||||
#[inline]
|
||||
pub fn set_fov(&mut self, fov: N) {
|
||||
self.fov = fov;
|
||||
pub fn set_fovy(&mut self, fovy: N) {
|
||||
self.fovy = fovy;
|
||||
}
|
||||
|
||||
/// Sets the near plane offset of the view frustrum.
|
||||
@ -132,19 +136,19 @@ impl<N: BaseFloat + Clone> Persp3<N> {
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> PerspMat3<N> {
|
||||
/// Creates a new persepctive matrix from the aspect ratio, field of view, and near/far planes.
|
||||
pub fn new(aspect: N, fov: N, znear: N, zfar: N) -> PerspMat3<N> {
|
||||
/// Creates a new perspective matrix from the aspect ratio, y field of view, and near/far planes.
|
||||
pub fn new(aspect: N, fovy: N, znear: N, zfar: N) -> PerspMat3<N> {
|
||||
assert!(!::is_zero(&(znear - zfar)));
|
||||
assert!(!::is_zero(&aspect));
|
||||
|
||||
let mat: Mat4<N> = ::one();
|
||||
|
||||
let mut res = PerspMat3 { mat: mat };
|
||||
res.set_fov(fov);
|
||||
res.set_fovy(fovy);
|
||||
res.set_aspect(aspect);
|
||||
res.set_znear_and_zfar(znear, zfar);
|
||||
res.mat.m44 = ::zero();
|
||||
res.mat.m43 = ::one();
|
||||
res.mat.m43 = -::one::<N>();
|
||||
|
||||
res
|
||||
}
|
||||
@ -168,12 +172,12 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
/// Gets the `width / height` aspect ratio of the view frustrum.
|
||||
#[inline]
|
||||
pub fn aspect(&self) -> N {
|
||||
-self.mat.m22 / self.mat.m11
|
||||
self.mat.m22 / self.mat.m11
|
||||
}
|
||||
|
||||
/// Gets the field of view of the view frustrum.
|
||||
/// Gets the y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn fov(&self) -> N {
|
||||
pub fn fovy(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
@ -185,7 +189,7 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
pub fn znear(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let ratio = (self.mat.m33 + _1) / (self.mat.m33 - _1);
|
||||
let ratio = (-self.mat.m33 + _1) / (-self.mat.m33 - _1);
|
||||
|
||||
self.mat.m34 / (_2 * ratio) - self.mat.m34 / _2
|
||||
}
|
||||
@ -195,29 +199,29 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
pub fn zfar(&self) -> N {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
let ratio = (self.mat.m33 + _1) / (self.mat.m33 - _1);
|
||||
let ratio = (-self.mat.m33 + _1) / (-self.mat.m33 - _1);
|
||||
|
||||
(self.mat.m34 - ratio * self.mat.m34) / _2
|
||||
}
|
||||
|
||||
// FIXME: add a method to retriev znear and zfar at once ?
|
||||
// FIXME: add a method to retrieve znear and zfar simultaneously?
|
||||
|
||||
/// Updates this projection matrix with a new `width / height` aspect ratio of the view
|
||||
/// frustrum.
|
||||
#[inline]
|
||||
pub fn set_aspect(&mut self, aspect: N) {
|
||||
assert!(!::is_zero(&aspect));
|
||||
self.mat.m11 = -self.mat.m22 / aspect;
|
||||
self.mat.m11 = self.mat.m22 / aspect;
|
||||
}
|
||||
|
||||
/// Updates this projection with a new field of view of the view frustrum.
|
||||
/// Updates this projection with a new y field of view of the view frustrum.
|
||||
#[inline]
|
||||
pub fn set_fov(&mut self, fov: N) {
|
||||
pub fn set_fovy(&mut self, fovy: N) {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
let old_m22 = self.mat.m22.clone();
|
||||
self.mat.m22 = _1 / (fov / _2).tan();
|
||||
self.mat.m22 = _1 / (fovy / _2).tan();
|
||||
self.mat.m11 = self.mat.m11 * (self.mat.m22 / old_m22);
|
||||
}
|
||||
|
||||
@ -241,7 +245,7 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
let _1: N = ::one();
|
||||
let _2 = _1 + _1;
|
||||
|
||||
self.mat.m33 = -(zfar + znear) / (znear - zfar);
|
||||
self.mat.m33 = (zfar + znear) / (znear - zfar);
|
||||
self.mat.m34 = zfar * znear * _2 / (znear - zfar);
|
||||
}
|
||||
|
||||
@ -249,7 +253,7 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
#[inline]
|
||||
pub fn project_pnt(&self, p: &Pnt3<N>) -> Pnt3<N> {
|
||||
let _1: N = ::one();
|
||||
let inv_denom = _1 / p.z;
|
||||
let inv_denom = -_1 / p.z;
|
||||
Pnt3::new(
|
||||
self.mat.m11 * p.x * inv_denom,
|
||||
self.mat.m22 * p.y * inv_denom,
|
||||
@ -261,7 +265,7 @@ impl<N: BaseFloat> PerspMat3<N> {
|
||||
#[inline]
|
||||
pub fn project_vec(&self, p: &Vec3<N>) -> Vec3<N> {
|
||||
let _1: N = ::one();
|
||||
let inv_denom = _1 / p.z;
|
||||
let inv_denom = -_1 / p.z;
|
||||
Vec3::new(
|
||||
self.mat.m11 * p.x * inv_denom,
|
||||
self.mat.m22 * p.y * inv_denom,
|
||||
|
@ -1,9 +1,7 @@
|
||||
//! Points with dimensions known at compile-time.
|
||||
//! Points with dimension known at compile-time.
|
||||
|
||||
#![allow(missing_docs)] // we allow missing to avoid having to document the point components.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::iter::{Iterator, FromIterator, IntoIterator};
|
||||
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
|
||||
@ -18,27 +16,10 @@ use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
|
||||
/// Point of dimension 0.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||
pub struct Pnt0<N>(pub PhantomData<N>);
|
||||
|
||||
impl<N> Pnt0<N> {
|
||||
/// Creates a new point.
|
||||
#[inline]
|
||||
pub fn new() -> Pnt0<N> {
|
||||
Pnt0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Repeat<N> for Pnt0<N> {
|
||||
#[inline]
|
||||
fn repeat(_: N) -> Pnt0<N> {
|
||||
Pnt0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Point of dimension 1.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt1<N> {
|
||||
@ -48,7 +29,7 @@ pub struct Pnt1<N> {
|
||||
|
||||
new_impl!(Pnt1, x);
|
||||
orig_impl!(Pnt1, x);
|
||||
ord_impl!(Pnt1, x,);
|
||||
pord_impl!(Pnt1, x,);
|
||||
scalar_mul_impl!(Pnt1, x);
|
||||
scalar_div_impl!(Pnt1, x);
|
||||
scalar_add_impl!(Pnt1, x);
|
||||
@ -77,8 +58,12 @@ pnt_from_homogeneous_impl!(Pnt1, Pnt2, y, x);
|
||||
num_float_pnt_impl!(Pnt1, Vec1);
|
||||
arbitrary_pnt_impl!(Pnt1, x);
|
||||
rand_impl!(Pnt1, x);
|
||||
pnt_display_impl!(Pnt1);
|
||||
|
||||
/// Point of dimension 2.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt2<N> {
|
||||
@ -90,7 +75,7 @@ pub struct Pnt2<N> {
|
||||
|
||||
new_impl!(Pnt2, x, y);
|
||||
orig_impl!(Pnt2, x, y);
|
||||
ord_impl!(Pnt2, x, y);
|
||||
pord_impl!(Pnt2, x, y);
|
||||
scalar_mul_impl!(Pnt2, x, y);
|
||||
scalar_div_impl!(Pnt2, x, y);
|
||||
scalar_add_impl!(Pnt2, x, y);
|
||||
@ -119,8 +104,12 @@ pnt_from_homogeneous_impl!(Pnt2, Pnt3, z, x, y);
|
||||
num_float_pnt_impl!(Pnt2, Vec2);
|
||||
arbitrary_pnt_impl!(Pnt2, x, y);
|
||||
rand_impl!(Pnt2, x, y);
|
||||
pnt_display_impl!(Pnt2);
|
||||
|
||||
/// Point of dimension 3.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt3<N> {
|
||||
@ -134,7 +123,7 @@ pub struct Pnt3<N> {
|
||||
|
||||
new_impl!(Pnt3, x, y, z);
|
||||
orig_impl!(Pnt3, x, y, z);
|
||||
ord_impl!(Pnt3, x, y, z);
|
||||
pord_impl!(Pnt3, x, y, z);
|
||||
scalar_mul_impl!(Pnt3, x, y, z);
|
||||
scalar_div_impl!(Pnt3, x, y, z);
|
||||
scalar_add_impl!(Pnt3, x, y, z);
|
||||
@ -163,8 +152,12 @@ pnt_from_homogeneous_impl!(Pnt3, Pnt4, w, x, y, z);
|
||||
num_float_pnt_impl!(Pnt3, Vec3);
|
||||
arbitrary_pnt_impl!(Pnt3, x, y, z);
|
||||
rand_impl!(Pnt3, x, y, z);
|
||||
pnt_display_impl!(Pnt3);
|
||||
|
||||
/// Point of dimension 4.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt4<N> {
|
||||
@ -180,7 +173,7 @@ pub struct Pnt4<N> {
|
||||
|
||||
new_impl!(Pnt4, x, y, z, w);
|
||||
orig_impl!(Pnt4, x, y, z, w);
|
||||
ord_impl!(Pnt4, x, y, z, w);
|
||||
pord_impl!(Pnt4, x, y, z, w);
|
||||
scalar_mul_impl!(Pnt4, x, y, z, w);
|
||||
scalar_div_impl!(Pnt4, x, y, z, w);
|
||||
scalar_add_impl!(Pnt4, x, y, z, w);
|
||||
@ -209,8 +202,12 @@ pnt_from_homogeneous_impl!(Pnt4, Pnt5, a, x, y, z, w);
|
||||
num_float_pnt_impl!(Pnt4, Vec4);
|
||||
arbitrary_pnt_impl!(Pnt4, x, y, z, w);
|
||||
rand_impl!(Pnt4, x, y, z, w);
|
||||
pnt_display_impl!(Pnt4);
|
||||
|
||||
/// Point of dimension 5.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt5<N> {
|
||||
@ -228,7 +225,7 @@ pub struct Pnt5<N> {
|
||||
|
||||
new_impl!(Pnt5, x, y, z, w, a);
|
||||
orig_impl!(Pnt5, x, y, z, w, a);
|
||||
ord_impl!(Pnt5, x, y, z, w, a);
|
||||
pord_impl!(Pnt5, x, y, z, w, a);
|
||||
scalar_mul_impl!(Pnt5, x, y, z, w, a);
|
||||
scalar_div_impl!(Pnt5, x, y, z, w, a);
|
||||
scalar_add_impl!(Pnt5, x, y, z, w, a);
|
||||
@ -257,8 +254,12 @@ pnt_from_homogeneous_impl!(Pnt5, Pnt6, b, x, y, z, w, a);
|
||||
num_float_pnt_impl!(Pnt5, Vec5);
|
||||
arbitrary_pnt_impl!(Pnt5, x, y, z, w, a);
|
||||
rand_impl!(Pnt5, x, y, z, w, a);
|
||||
pnt_display_impl!(Pnt5);
|
||||
|
||||
/// Point of dimension 6.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Pnt6<N> {
|
||||
@ -278,7 +279,7 @@ pub struct Pnt6<N> {
|
||||
|
||||
new_impl!(Pnt6, x, y, z, w, a, b);
|
||||
orig_impl!(Pnt6, x, y, z, w, a, b);
|
||||
ord_impl!(Pnt6, x, y, z, w, a, b);
|
||||
pord_impl!(Pnt6, x, y, z, w, a, b);
|
||||
scalar_mul_impl!(Pnt6, x, y, z, w, a, b);
|
||||
scalar_div_impl!(Pnt6, x, y, z, w, a, b);
|
||||
scalar_add_impl!(Pnt6, x, y, z, w, a, b);
|
||||
@ -305,3 +306,4 @@ iterable_mut_impl!(Pnt6, 6);
|
||||
num_float_pnt_impl!(Pnt6, Vec6);
|
||||
arbitrary_pnt_impl!(Pnt6, x, y, z, w, a, b);
|
||||
rand_impl!(Pnt6, x, y, z, w, a, b);
|
||||
pnt_display_impl!(Pnt6);
|
||||
|
@ -155,3 +155,24 @@ macro_rules! arbitrary_pnt_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! pnt_display_impl(
|
||||
($t: ident) => (
|
||||
impl<N: fmt::Display> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// FIXME: differenciate them from vectors ?
|
||||
try!(write!(f, "("));
|
||||
|
||||
let mut it = self.iter();
|
||||
|
||||
try!(write!(f, "{}", *it.next().unwrap()));
|
||||
|
||||
for comp in it {
|
||||
try!(write!(f, ", {}", *comp));
|
||||
}
|
||||
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! Quaternion definition.
|
||||
|
||||
#![allow(missing_docs)] // we allow missing to avoid having to document the dispatch trait.
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
|
||||
@ -156,6 +155,12 @@ impl<N: ApproxEq<N> + BaseFloat> Div<Quat<N>> for Quat<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Display> fmt::Display for Quat<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Quaternion {} − ({}, {}, {})", self.w, self.i, self.j, self.k)
|
||||
}
|
||||
}
|
||||
|
||||
rand_impl!(Quat, w, i, j, k);
|
||||
|
||||
|
||||
@ -507,6 +512,12 @@ impl<N: BaseNum + Neg<Output = N>> Transform<Pnt3<N>> for UnitQuat<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Display> fmt::Display for UnitQuat<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Unit quaternion {} − ({}, {}, {})", self.q.w, self.q.i, self.q.j, self.q.k)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuat<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> UnitQuat<N> {
|
||||
@ -515,7 +526,7 @@ impl<N: Arbitrary + BaseFloat> Arbitrary for UnitQuat<N> {
|
||||
}
|
||||
|
||||
|
||||
ord_impl!(Quat, w, i, j, k);
|
||||
pord_impl!(Quat, w, i, j, k);
|
||||
vec_axis_impl!(Quat, w, i, j, k);
|
||||
vec_cast_impl!(Quat, w, i, j, k);
|
||||
conversion_impl!(Quat, 4);
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! Rotations matrices.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Mul, Neg, Index};
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
@ -9,9 +8,9 @@ use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Rotatio
|
||||
ToHomogeneous, Norm, Cross};
|
||||
use traits::structure::{Cast, Dim, Row, Col, BaseFloat, BaseNum, Eye, Diag};
|
||||
use traits::operations::{Absolute, Inv, Transpose, ApproxEq};
|
||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
||||
use structs::pnt::{Pnt2, Pnt3, Pnt4};
|
||||
use structs::mat::{Mat2, Mat3, Mat4, Mat5};
|
||||
use structs::vec::{Vec1, Vec2, Vec3};
|
||||
use structs::pnt::{Pnt2, Pnt3};
|
||||
use structs::mat::{Mat2, Mat3, Mat4};
|
||||
#[cfg(feature="arbitrary")]
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
@ -195,47 +194,59 @@ impl<N: Clone + BaseFloat> Rot3<N> {
|
||||
}
|
||||
|
||||
impl<N: Clone + BaseFloat> Rot3<N> {
|
||||
/// Create a new matrix and orient it 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.
|
||||
/// Creates a rotation that corresponds to the local frame of an observer standing at the
|
||||
/// origin and looking toward `dir`.
|
||||
///
|
||||
/// It maps the view direction `dir` to the positive `z` axis.
|
||||
///
|
||||
/// # 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(at: &Vec3<N>, up: &Vec3<N>) -> Rot3<N> {
|
||||
let xaxis = Norm::normalize(at);
|
||||
let zaxis = Norm::normalize(&Cross::cross(up, &xaxis));
|
||||
let yaxis = Cross::cross(&zaxis, &xaxis);
|
||||
/// * dir - The look direction, that is, direction the matrix `z` axis will be aligned with.
|
||||
/// * up - The vertical direction. The only requirement of this parameter is to not be
|
||||
/// collinear
|
||||
/// to `dir`. Non-collinearity is not checked.
|
||||
#[inline]
|
||||
pub fn new_observer_frame(dir: &Vec3<N>, up: &Vec3<N>) -> Rot3<N> {
|
||||
let zaxis = Norm::normalize(dir);
|
||||
let xaxis = Norm::normalize(&Cross::cross(up, &zaxis));
|
||||
let yaxis = Norm::normalize(&Cross::cross(&zaxis, &xaxis));
|
||||
|
||||
unsafe {
|
||||
Rot3::new_with_mat(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)
|
||||
)
|
||||
xaxis.z , yaxis.z , zaxis.z))
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new matrix and orient it such that its local `z` axis points to a given point.
|
||||
|
||||
/// Builds a right-handed look-at view matrix without translation.
|
||||
///
|
||||
/// This conforms to the common notion of right handed look-at matrix from the computer
|
||||
/// graphics community.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * at - The look direction, that is, 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(at: &Vec3<N>, up: &Vec3<N>) -> Rot3<N> {
|
||||
let zaxis = Norm::normalize(at);
|
||||
let xaxis = Norm::normalize(&Cross::cross(up, &zaxis));
|
||||
let yaxis = Cross::cross(&zaxis, &xaxis);
|
||||
/// * eye - The eye position.
|
||||
/// * target - The target position.
|
||||
/// * up - A vector approximately aligned with required the vertical axis. The only
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_rh(dir: &Vec3<N>, up: &Vec3<N>) -> Rot3<N> {
|
||||
Rot3::new_observer_frame(&(-*dir), up).inv().unwrap()
|
||||
}
|
||||
|
||||
unsafe {
|
||||
Rot3::new_with_mat(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)
|
||||
)
|
||||
}
|
||||
/// Builds a left-handed look-at view matrix without translation.
|
||||
///
|
||||
/// This conforms to the common notion of left handed look-at matrix from the computer
|
||||
/// graphics community.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * eye - The eye position.
|
||||
/// * target - The target position.
|
||||
/// * up - A vector approximately aligned with required the vertical axis. The only
|
||||
/// requirement of this parameter is to not be collinear to `target - eye`.
|
||||
#[inline]
|
||||
pub fn look_at_lh(dir: &Vec3<N>, up: &Vec3<N>) -> Rot3<N> {
|
||||
Rot3::new_observer_frame(&(*dir), up).inv().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,92 +356,6 @@ impl<N: Arbitrary + Clone + BaseFloat> Arbitrary for Rot3<N> {
|
||||
}
|
||||
|
||||
|
||||
/// Four dimensional rotation matrix.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Hash, Copy)]
|
||||
pub struct Rot4<N> {
|
||||
submat: Mat4<N>
|
||||
}
|
||||
|
||||
// impl<N> Rot4<N> {
|
||||
// pub fn new(left_iso: Quat<N>, right_iso: Quat<N>) -> Rot4<N> {
|
||||
// assert!(left_iso.is_unit());
|
||||
// assert!(right_iso.is_unright);
|
||||
//
|
||||
// let mat_left_iso = Mat4::new(
|
||||
// left_iso.x, -left_iso.y, -left_iso.z, -left_iso.w,
|
||||
// left_iso.y, left_iso.x, -left_iso.w, left_iso.z,
|
||||
// left_iso.z, left_iso.w, left_iso.x, -left_iso.y,
|
||||
// left_iso.w, -left_iso.z, left_iso.y, left_iso.x);
|
||||
// let mat_right_iso = Mat4::new(
|
||||
// right_iso.x, -right_iso.y, -right_iso.z, -right_iso.w,
|
||||
// right_iso.y, right_iso.x, right_iso.w, -right_iso.z,
|
||||
// right_iso.z, -right_iso.w, right_iso.x, right_iso.y,
|
||||
// right_iso.w, right_iso.z, -right_iso.y, right_iso.x);
|
||||
//
|
||||
// Rot4 {
|
||||
// submat: mat_left_iso * mat_right_iso
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<N: BaseFloat> AbsoluteRotate<Vec4<N>> for Rot4<N> {
|
||||
#[inline]
|
||||
fn absolute_rotate(&self, v: &Vec4<N>) -> Vec4<N> {
|
||||
Vec4::new(
|
||||
::abs(&self.submat.m11) * v.x + ::abs(&self.submat.m12) * v.y +
|
||||
::abs(&self.submat.m13) * v.z + ::abs(&self.submat.m14) * v.w,
|
||||
|
||||
::abs(&self.submat.m21) * v.x + ::abs(&self.submat.m22) * v.y +
|
||||
::abs(&self.submat.m23) * v.z + ::abs(&self.submat.m24) * v.w,
|
||||
|
||||
::abs(&self.submat.m31) * v.x + ::abs(&self.submat.m32) * v.y +
|
||||
::abs(&self.submat.m33) * v.z + ::abs(&self.submat.m34) * v.w,
|
||||
|
||||
::abs(&self.submat.m41) * v.x + ::abs(&self.submat.m42) * v.y +
|
||||
::abs(&self.submat.m43) * v.z + ::abs(&self.submat.m44) * v.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Clone>
|
||||
Rotation<Vec4<N>> for Rot4<N> {
|
||||
#[inline]
|
||||
fn rotation(&self) -> Vec4<N> {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_rotation(&self) -> Vec4<N> {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_rotation_mut(&mut self, _: &Vec4<N>) {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_rotation(&self, _: &Vec4<N>) -> Rot4<N> {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation_mut(&mut self, _: &Vec4<N>) {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_rotation(&self, _: &Vec4<N>) -> Rot4<N> {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_rotation(&mut self, _: Vec4<N>) {
|
||||
panic!("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common implementations.
|
||||
*/
|
||||
@ -456,6 +381,7 @@ inv_impl!(Rot2);
|
||||
transpose_impl!(Rot2);
|
||||
approx_eq_impl!(Rot2);
|
||||
diag_impl!(Rot2, Vec2);
|
||||
rot_display_impl!(Rot2);
|
||||
|
||||
submat_impl!(Rot3, Mat3);
|
||||
rotate_impl!(Rot3, Vec3, Pnt3);
|
||||
@ -478,25 +404,4 @@ inv_impl!(Rot3);
|
||||
transpose_impl!(Rot3);
|
||||
approx_eq_impl!(Rot3);
|
||||
diag_impl!(Rot3, Vec3);
|
||||
|
||||
submat_impl!(Rot4, Mat4);
|
||||
rotate_impl!(Rot4, Vec4, Pnt4);
|
||||
transform_impl!(Rot4, Vec4, Pnt4);
|
||||
dim_impl!(Rot4, 4);
|
||||
rot_mul_rot_impl!(Rot4);
|
||||
rot_mul_vec_impl!(Rot4, Vec4);
|
||||
vec_mul_rot_impl!(Rot4, Vec4);
|
||||
rot_mul_pnt_impl!(Rot4, Pnt4);
|
||||
pnt_mul_rot_impl!(Rot4, Pnt4);
|
||||
one_impl!(Rot4);
|
||||
eye_impl!(Rot4);
|
||||
rotation_matrix_impl!(Rot4, Vec4, Vec4);
|
||||
col_impl!(Rot4, Vec4);
|
||||
row_impl!(Rot4, Vec4);
|
||||
index_impl!(Rot4);
|
||||
absolute_impl!(Rot4, Mat4);
|
||||
to_homogeneous_impl!(Rot4, Mat5);
|
||||
inv_impl!(Rot4);
|
||||
transpose_impl!(Rot4);
|
||||
approx_eq_impl!(Rot4);
|
||||
diag_impl!(Rot4, Vec4);
|
||||
rot_display_impl!(Rot3);
|
||||
|
@ -3,6 +3,7 @@
|
||||
macro_rules! submat_impl(
|
||||
($t: ident, $submat: ident) => (
|
||||
impl<N> $t<N> {
|
||||
/// This rotation's underlying matrix.
|
||||
#[inline]
|
||||
pub fn submat<'r>(&'r self) -> &'r $submat<N> {
|
||||
&self.submat
|
||||
@ -325,3 +326,17 @@ macro_rules! absolute_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! rot_display_impl(
|
||||
($t: ident) => (
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let precision = f.precision().unwrap_or(3);
|
||||
|
||||
try!(writeln!(f, "Rotation matrix {{"));
|
||||
try!(write!(f, "{:.*}", precision, self.submat));
|
||||
writeln!(f, "}}")
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
86
src/structs/sim.rs
Normal file
86
src/structs/sim.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use std::fmt;
|
||||
use std::ops::{Mul, Neg};
|
||||
|
||||
use rand::{Rand, Rng};
|
||||
use num::One;
|
||||
use structs::mat::{Mat3, Mat4};
|
||||
use traits::structure::{Dim, Col, BaseFloat, BaseNum};
|
||||
use traits::operations::{Inv, ApproxEq};
|
||||
use traits::geometry::{Rotation, Transform, Transformation, Translation, ToHomogeneous};
|
||||
|
||||
use structs::vec::{Vec1, Vec2, Vec3};
|
||||
use structs::pnt::{Pnt2, Pnt3};
|
||||
use structs::rot::{Rot2, Rot3};
|
||||
use structs::iso::{Iso2, Iso3};
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
// FIXME: the name is not explicit at all but coherent with the other tree-letters names…
|
||||
/// A two-dimensional similarity transformation.
|
||||
///
|
||||
/// This is a composition of a uniform scale, followed by a rotation, followed by a translation.
|
||||
/// Vectors `Vec2` are not affected by the translational component of this transformation while
|
||||
/// points `Pnt2` are.
|
||||
/// Similarity transformations conserve angles. Distances are multiplied by some constant (the
|
||||
/// scale factor). The scale factor cannot be zero.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct Sim2<N> {
|
||||
/// The uniform scale applicable by this similarity transformation.
|
||||
scale: N,
|
||||
/// The isometry applicable by this similarity transformation.
|
||||
pub isometry: Iso2<N>
|
||||
}
|
||||
|
||||
/// A three-dimensional similarity transformation.
|
||||
///
|
||||
/// This is a composition of a scale, followed by a rotation, followed by a translation.
|
||||
/// Vectors `Vec3` are not affected by the translational component of this transformation while
|
||||
/// points `Pnt3` are.
|
||||
/// Similarity transformations conserve angles. Distances are multiplied by some constant (the
|
||||
/// scale factor). The scale factor cannot be zero.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
|
||||
pub struct Sim3<N> {
|
||||
/// The uniform scale applicable by this similarity transformation.
|
||||
scale: N,
|
||||
/// The isometry applicable by this similarity transformation.
|
||||
pub isometry: Iso3<N>
|
||||
}
|
||||
|
||||
sim_impl!(Sim2, Iso2, Rot2, Vec2, Vec1);
|
||||
dim_impl!(Sim2, 2);
|
||||
sim_scale_impl!(Sim2);
|
||||
sim_one_impl!(Sim2);
|
||||
sim_mul_sim_impl!(Sim2);
|
||||
sim_mul_iso_impl!(Sim2, Iso2);
|
||||
sim_mul_rot_impl!(Sim2, Rot2);
|
||||
sim_mul_pnt_vec_impl!(Sim2, Pnt2);
|
||||
sim_mul_pnt_vec_impl!(Sim2, Vec2);
|
||||
transformation_impl!(Sim2);
|
||||
sim_transform_impl!(Sim2, Pnt2);
|
||||
sim_inv_impl!(Sim2);
|
||||
sim_to_homogeneous_impl!(Sim2, Mat3);
|
||||
sim_approx_eq_impl!(Sim2);
|
||||
sim_rand_impl!(Sim2);
|
||||
sim_arbitrary_impl!(Sim2);
|
||||
sim_display_impl!(Sim2);
|
||||
|
||||
sim_impl!(Sim3, Iso3, Rot3, Vec3, Vec3);
|
||||
dim_impl!(Sim3, 3);
|
||||
sim_scale_impl!(Sim3);
|
||||
sim_one_impl!(Sim3);
|
||||
sim_mul_sim_impl!(Sim3);
|
||||
sim_mul_iso_impl!(Sim3, Iso3);
|
||||
sim_mul_rot_impl!(Sim3, Rot3);
|
||||
sim_mul_pnt_vec_impl!(Sim3, Pnt3);
|
||||
sim_mul_pnt_vec_impl!(Sim3, Vec3);
|
||||
transformation_impl!(Sim3);
|
||||
sim_transform_impl!(Sim3, Pnt3);
|
||||
sim_inv_impl!(Sim3);
|
||||
sim_to_homogeneous_impl!(Sim3, Mat4);
|
||||
sim_approx_eq_impl!(Sim3);
|
||||
sim_rand_impl!(Sim3);
|
||||
sim_arbitrary_impl!(Sim3);
|
||||
sim_display_impl!(Sim3);
|
343
src/structs/sim_macros.rs
Normal file
343
src/structs/sim_macros.rs
Normal file
@ -0,0 +1,343 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! sim_impl(
|
||||
($t: ident, $iso: ident, $rotmat: ident, $subvec: ident, $subrotvec: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/// Creates a new similarity transformation from a vector, an axis-angle rotation, and a scale factor.
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
scale: scale,
|
||||
isometry: $iso::new(translation, rotation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new similarity transformation from a rotation matrix, a vector, and a scale factor.
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new_with_rotmat(translation: $subvec<N>, rotation: $rotmat<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
scale: scale,
|
||||
isometry: $iso::new_with_rotmat(translation, rotation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new similarity transformation from an isometry and a scale factor.
|
||||
///
|
||||
/// The scale factor may be negative but not zero.
|
||||
#[inline]
|
||||
pub fn new_with_iso(isometry: $iso<N>, scale: N) -> $t<N> {
|
||||
assert!(!scale.is_zero(), "A similarity transformation scale factor cannot be zero.");
|
||||
|
||||
$t {
|
||||
scale: scale,
|
||||
isometry: isometry
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_scale_impl(
|
||||
($t: ident) => (
|
||||
impl<N: BaseFloat> $t<N> {
|
||||
/// The scale factor of this similarity transformation.
|
||||
#[inline]
|
||||
pub fn scale(&self) -> N {
|
||||
self.scale
|
||||
}
|
||||
|
||||
/// The inverse scale factor of this similarity transformation.
|
||||
#[inline]
|
||||
pub fn inv_scale(&self) -> N {
|
||||
::one::<N>() / self.scale
|
||||
}
|
||||
|
||||
/// Appends in-place a scale to this similarity transformation.
|
||||
#[inline]
|
||||
pub fn append_scale_mut(&mut self, s: &N) {
|
||||
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation.");
|
||||
self.scale = *s * self.scale;
|
||||
self.isometry.translation = self.isometry.translation * *s;
|
||||
}
|
||||
|
||||
/// Appends a scale to this similarity transformation.
|
||||
#[inline]
|
||||
pub fn append_scale(&self, s: &N) -> $t<N> {
|
||||
assert!(!s.is_zero(), "Cannot append a zero scale to a similarity transformation.");
|
||||
$t::new_with_rotmat(self.isometry.translation * *s, self.isometry.rotation, self.scale * *s)
|
||||
}
|
||||
|
||||
/// Prepends in-place a scale to this similarity transformation.
|
||||
#[inline]
|
||||
pub fn prepend_scale_mut(&mut self, s: &N) {
|
||||
assert!(!s.is_zero(), "Cannot prepend a zero scale to a similarity transformation.");
|
||||
self.scale = self.scale * *s;
|
||||
}
|
||||
|
||||
/// Prepends a scale to this similarity transformation.
|
||||
#[inline]
|
||||
pub fn prepend_scale(&self, s: &N) -> $t<N> {
|
||||
assert!(!s.is_zero(), "A similarity transformation scale must not be zero.");
|
||||
$t::new_with_iso(self.isometry, self.scale * *s)
|
||||
}
|
||||
|
||||
/// Sets the scale of this similarity transformation.
|
||||
#[inline]
|
||||
pub fn set_scale(&mut self, s: N) {
|
||||
assert!(!s.is_zero(), "A similarity transformation scale must not be zero.");
|
||||
self.scale = s
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_one_impl(
|
||||
($t: ident) => (
|
||||
impl<N: BaseFloat> One for $t<N> {
|
||||
#[inline]
|
||||
fn one() -> $t<N> {
|
||||
$t::new_with_iso(::one(), ::one())
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_sim_impl(
|
||||
($t: ident) => (
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self.isometry.translation + self.isometry.rotation * (right.isometry.translation * self.scale),
|
||||
self.isometry.rotation * right.isometry.rotation,
|
||||
self.scale * right.scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_iso_impl(
|
||||
($t: ident, $ti: ident) => (
|
||||
impl<N: BaseFloat> Mul<$ti<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $ti<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self.isometry.translation + self.isometry.rotation * (right.translation * self.scale),
|
||||
self.isometry.rotation * right.rotation,
|
||||
self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $ti<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self.translation + self.rotation * right.isometry.translation,
|
||||
self.rotation * right.isometry.rotation,
|
||||
right.scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_rot_impl(
|
||||
($t: ident, $tr: ident) => (
|
||||
impl<N: BaseFloat> Mul<$tr<N>> for $t<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tr<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self.isometry.translation,
|
||||
self.isometry.rotation * right,
|
||||
self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Mul<$t<N>> for $tr<N> {
|
||||
type Output = $t<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $t<N>) -> $t<N> {
|
||||
$t::new_with_rotmat(
|
||||
self * right.isometry.translation,
|
||||
self * right.isometry.rotation,
|
||||
right.scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_mul_pnt_vec_impl(
|
||||
($t: ident, $tv: ident) => (
|
||||
impl<N: BaseNum> Mul<$tv<N>> for $t<N> {
|
||||
type Output = $tv<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $tv<N>) -> $tv<N> {
|
||||
self.isometry * (right * self.scale)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE: there is no viable pre-multiplication definition because of the translation
|
||||
// component.
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_transform_impl(
|
||||
($t: ident, $tp: ident) => (
|
||||
impl<N: BaseNum> Transform<$tp<N>> for $t<N> {
|
||||
#[inline]
|
||||
fn transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
self.isometry.transform(&(*p * self.scale))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_transform(&self, p: &$tp<N>) -> $tp<N> {
|
||||
self.isometry.inv_transform(p) / self.scale
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_inv_impl(
|
||||
($t: ident) => (
|
||||
impl<N: BaseNum + Neg<Output = N>> Inv for $t<N> {
|
||||
#[inline]
|
||||
fn inv_mut(&mut self) -> bool {
|
||||
self.scale = ::one::<N>() / self.scale;
|
||||
self.isometry.inv_mut();
|
||||
// We multiply (instead of dividing) by self.scale because it has already been
|
||||
// inverted.
|
||||
self.isometry.translation = self.isometry.translation * self.scale;
|
||||
|
||||
// Always succeed.
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv(&self) -> Option<$t<N>> {
|
||||
let mut res = *self;
|
||||
res.inv_mut();
|
||||
|
||||
// Always succeed.
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_to_homogeneous_impl(
|
||||
($t: ident, $th: ident) => (
|
||||
impl<N: BaseNum> ToHomogeneous<$th<N>> for $t<N> {
|
||||
fn to_homogeneous(&self) -> $th<N> {
|
||||
let mut res = (*self.isometry.rotation.submat() * self.scale).to_homogeneous();
|
||||
|
||||
// copy the translation
|
||||
let dim = Dim::dim(None::<$th<N>>);
|
||||
|
||||
res.set_col(dim - 1, self.isometry.translation.as_pnt().to_homogeneous().to_vec());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_approx_eq_impl(
|
||||
($t: ident) => (
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$t<N>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_ulps(_: Option<$t<N>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
|
||||
ApproxEq::approx_eq_eps(&self.scale, &other.scale, epsilon) &&
|
||||
ApproxEq::approx_eq_eps(&self.isometry, &other.isometry, epsilon)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &$t<N>, ulps: u32) -> bool {
|
||||
ApproxEq::approx_eq_ulps(&self.scale, &other.scale, ulps) &&
|
||||
ApproxEq::approx_eq_ulps(&self.isometry, &other.isometry, ulps)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_rand_impl(
|
||||
($t: ident) => (
|
||||
impl<N: Rand + BaseFloat> Rand for $t<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||
let mut scale: N = rng.gen();
|
||||
while scale.is_zero() {
|
||||
scale = rng.gen();
|
||||
}
|
||||
|
||||
$t::new_with_iso(rng.gen(), scale)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_arbitrary_impl(
|
||||
($t: ident) => (
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + BaseFloat> Arbitrary for $t<N> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> $t<N> {
|
||||
$t::new_with_iso(
|
||||
Arbitrary::arbitrary(g),
|
||||
Arbitrary::arbitrary(g)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! sim_display_impl(
|
||||
($t: ident) => (
|
||||
impl<N: fmt::Display + BaseFloat> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(writeln!(f, "Similarity transformation {{"));
|
||||
|
||||
if let Some(precision) = f.precision() {
|
||||
try!(writeln!(f, "... scale factor: {:.*}", precision, self.scale));
|
||||
try!(writeln!(f, "... translation: {:.*}", precision, self.isometry.translation));
|
||||
try!(writeln!(f, "... rotation matrix:"));
|
||||
try!(write!(f, "{:.*}", precision, *self.isometry.rotation.submat()));
|
||||
}
|
||||
else {
|
||||
try!(writeln!(f, "... scale factor: {}", self.scale));
|
||||
try!(writeln!(f, "... translation: {}", self.isometry.translation));
|
||||
try!(writeln!(f, "... rotation matrix:"));
|
||||
try!(write!(f, "{}", *self.isometry.rotation.submat()));
|
||||
}
|
||||
|
||||
writeln!(f, "}}")
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
@ -1,219 +1,170 @@
|
||||
//! nalgebra trait implementation for primitive types.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use traits::structure::Cast;
|
||||
|
||||
// Double dispatch traits to drive the Cast method for primitive types.
|
||||
macro_rules! primitive_double_dispatch_cast_decl_trait(
|
||||
($t: ident, $tcast: ident) => (
|
||||
pub trait $tcast {
|
||||
fn to(Self) -> $t;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! primitive_double_dispatch_cast_impl(
|
||||
($ttarget: ident, $tself: ident, $tcast: ident) => (
|
||||
impl $tcast for $tself{
|
||||
macro_rules! primitive_cast_impl(
|
||||
($from: ty, $to: ty) => (
|
||||
impl Cast<$from> for $to {
|
||||
#[inline(always)]
|
||||
fn to(v: $tself) -> $ttarget {
|
||||
v as $ttarget
|
||||
fn from(t: $from) -> $to {
|
||||
t as $to
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! primitive_cast_redispatch_impl(
|
||||
($t:ident, $tcast: ident) => (
|
||||
impl<T: $tcast> Cast<T> for $t {
|
||||
#[inline(always)]
|
||||
fn from(t: T) -> $t {
|
||||
$tcast::to(t)
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
primitive_cast_impl!(f64, f64);
|
||||
primitive_cast_impl!(f64, f32);
|
||||
primitive_cast_impl!(f64, i64);
|
||||
primitive_cast_impl!(f64, i32);
|
||||
primitive_cast_impl!(f64, i16);
|
||||
primitive_cast_impl!(f64, i8);
|
||||
primitive_cast_impl!(f64, u64);
|
||||
primitive_cast_impl!(f64, u32);
|
||||
primitive_cast_impl!(f64, u16);
|
||||
primitive_cast_impl!(f64, u8);
|
||||
primitive_cast_impl!(f64, isize);
|
||||
primitive_cast_impl!(f64, usize);
|
||||
|
||||
primitive_double_dispatch_cast_decl_trait!(f64, f64Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(f32, f32Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(i64, i64Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(i32, i32Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(i16, i16Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(i8, i8Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(u64, u64Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(u32, u32Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(u16, u16Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(u8, u8Cast);
|
||||
primitive_double_dispatch_cast_decl_trait!(isize, isizeCast);
|
||||
primitive_double_dispatch_cast_decl_trait!(usize, usizeCast);
|
||||
primitive_cast_impl!(f32, f64);
|
||||
primitive_cast_impl!(f32, f32);
|
||||
primitive_cast_impl!(f32, i64);
|
||||
primitive_cast_impl!(f32, i32);
|
||||
primitive_cast_impl!(f32, i16);
|
||||
primitive_cast_impl!(f32, i8);
|
||||
primitive_cast_impl!(f32, u64);
|
||||
primitive_cast_impl!(f32, u32);
|
||||
primitive_cast_impl!(f32, u16);
|
||||
primitive_cast_impl!(f32, u8);
|
||||
primitive_cast_impl!(f32, isize);
|
||||
primitive_cast_impl!(f32, usize);
|
||||
|
||||
primitive_cast_redispatch_impl!(f64, f64Cast);
|
||||
primitive_cast_redispatch_impl!(f32, f32Cast);
|
||||
primitive_cast_redispatch_impl!(i64, i64Cast);
|
||||
primitive_cast_redispatch_impl!(i32, i32Cast);
|
||||
primitive_cast_redispatch_impl!(i16, i16Cast);
|
||||
primitive_cast_redispatch_impl!(i8, i8Cast);
|
||||
primitive_cast_redispatch_impl!(u64, u64Cast);
|
||||
primitive_cast_redispatch_impl!(u32, u32Cast);
|
||||
primitive_cast_redispatch_impl!(u16, u16Cast);
|
||||
primitive_cast_redispatch_impl!(u8, u8Cast);
|
||||
primitive_cast_redispatch_impl!(isize, isizeCast);
|
||||
primitive_cast_redispatch_impl!(usize, usizeCast);
|
||||
primitive_cast_impl!(i64, f64);
|
||||
primitive_cast_impl!(i64, f32);
|
||||
primitive_cast_impl!(i64, i64);
|
||||
primitive_cast_impl!(i64, i32);
|
||||
primitive_cast_impl!(i64, i16);
|
||||
primitive_cast_impl!(i64, i8);
|
||||
primitive_cast_impl!(i64, u64);
|
||||
primitive_cast_impl!(i64, u32);
|
||||
primitive_cast_impl!(i64, u16);
|
||||
primitive_cast_impl!(i64, u8);
|
||||
primitive_cast_impl!(i64, isize);
|
||||
primitive_cast_impl!(i64, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(f64, f64, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, f32, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, i64, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, i32, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, i16, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, i8, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, u64, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, u32, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, u16, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, u8, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, isize, f64Cast);
|
||||
primitive_double_dispatch_cast_impl!(f64, usize, f64Cast);
|
||||
primitive_cast_impl!(i32, f64);
|
||||
primitive_cast_impl!(i32, f32);
|
||||
primitive_cast_impl!(i32, i64);
|
||||
primitive_cast_impl!(i32, i32);
|
||||
primitive_cast_impl!(i32, i16);
|
||||
primitive_cast_impl!(i32, i8);
|
||||
primitive_cast_impl!(i32, u64);
|
||||
primitive_cast_impl!(i32, u32);
|
||||
primitive_cast_impl!(i32, u16);
|
||||
primitive_cast_impl!(i32, u8);
|
||||
primitive_cast_impl!(i32, isize);
|
||||
primitive_cast_impl!(i32, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(f32, f64, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, f32, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, i64, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, i32, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, i16, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, i8, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, u64, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, u32, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, u16, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, u8, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, isize, f32Cast);
|
||||
primitive_double_dispatch_cast_impl!(f32, usize, f32Cast);
|
||||
primitive_cast_impl!(i16, f64);
|
||||
primitive_cast_impl!(i16, f32);
|
||||
primitive_cast_impl!(i16, i64);
|
||||
primitive_cast_impl!(i16, i32);
|
||||
primitive_cast_impl!(i16, i16);
|
||||
primitive_cast_impl!(i16, i8);
|
||||
primitive_cast_impl!(i16, u64);
|
||||
primitive_cast_impl!(i16, u32);
|
||||
primitive_cast_impl!(i16, u16);
|
||||
primitive_cast_impl!(i16, u8);
|
||||
primitive_cast_impl!(i16, isize);
|
||||
primitive_cast_impl!(i16, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(i64, f64, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, f32, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, i64, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, i32, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, i16, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, i8, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, u64, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, u32, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, u16, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, u8, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, isize, i64Cast);
|
||||
primitive_double_dispatch_cast_impl!(i64, usize, i64Cast);
|
||||
primitive_cast_impl!(i8, f64);
|
||||
primitive_cast_impl!(i8, f32);
|
||||
primitive_cast_impl!(i8, i64);
|
||||
primitive_cast_impl!(i8, i32);
|
||||
primitive_cast_impl!(i8, i16);
|
||||
primitive_cast_impl!(i8, i8);
|
||||
primitive_cast_impl!(i8, u64);
|
||||
primitive_cast_impl!(i8, u32);
|
||||
primitive_cast_impl!(i8, u16);
|
||||
primitive_cast_impl!(i8, u8);
|
||||
primitive_cast_impl!(i8, isize);
|
||||
primitive_cast_impl!(i8, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(i32, f64, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, f32, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, i64, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, i32, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, i16, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, i8, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, u64, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, u32, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, u16, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, u8, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, isize, i32Cast);
|
||||
primitive_double_dispatch_cast_impl!(i32, usize, i32Cast);
|
||||
primitive_cast_impl!(u64, f64);
|
||||
primitive_cast_impl!(u64, f32);
|
||||
primitive_cast_impl!(u64, i64);
|
||||
primitive_cast_impl!(u64, i32);
|
||||
primitive_cast_impl!(u64, i16);
|
||||
primitive_cast_impl!(u64, i8);
|
||||
primitive_cast_impl!(u64, u64);
|
||||
primitive_cast_impl!(u64, u32);
|
||||
primitive_cast_impl!(u64, u16);
|
||||
primitive_cast_impl!(u64, u8);
|
||||
primitive_cast_impl!(u64, isize);
|
||||
primitive_cast_impl!(u64, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(i16, f64, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, f32, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, i64, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, i32, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, i16, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, i8, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, u64, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, u32, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, u16, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, u8, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, isize, i16Cast);
|
||||
primitive_double_dispatch_cast_impl!(i16, usize, i16Cast);
|
||||
primitive_cast_impl!(u32, f64);
|
||||
primitive_cast_impl!(u32, f32);
|
||||
primitive_cast_impl!(u32, i64);
|
||||
primitive_cast_impl!(u32, i32);
|
||||
primitive_cast_impl!(u32, i16);
|
||||
primitive_cast_impl!(u32, i8);
|
||||
primitive_cast_impl!(u32, u64);
|
||||
primitive_cast_impl!(u32, u32);
|
||||
primitive_cast_impl!(u32, u16);
|
||||
primitive_cast_impl!(u32, u8);
|
||||
primitive_cast_impl!(u32, isize);
|
||||
primitive_cast_impl!(u32, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(i8, f64, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, f32, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, i64, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, i32, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, i16, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, i8, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, u64, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, u32, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, u16, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, u8, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, isize, i8Cast);
|
||||
primitive_double_dispatch_cast_impl!(i8, usize, i8Cast);
|
||||
primitive_cast_impl!(u16, f64);
|
||||
primitive_cast_impl!(u16, f32);
|
||||
primitive_cast_impl!(u16, i64);
|
||||
primitive_cast_impl!(u16, i32);
|
||||
primitive_cast_impl!(u16, i16);
|
||||
primitive_cast_impl!(u16, i8);
|
||||
primitive_cast_impl!(u16, u64);
|
||||
primitive_cast_impl!(u16, u32);
|
||||
primitive_cast_impl!(u16, u16);
|
||||
primitive_cast_impl!(u16, u8);
|
||||
primitive_cast_impl!(u16, isize);
|
||||
primitive_cast_impl!(u16, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(u64, f64, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, f32, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, i64, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, i32, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, i16, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, i8, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, u64, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, u32, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, u16, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, u8, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, isize, u64Cast);
|
||||
primitive_double_dispatch_cast_impl!(u64, usize, u64Cast);
|
||||
primitive_cast_impl!(u8, f64);
|
||||
primitive_cast_impl!(u8, f32);
|
||||
primitive_cast_impl!(u8, i64);
|
||||
primitive_cast_impl!(u8, i32);
|
||||
primitive_cast_impl!(u8, i16);
|
||||
primitive_cast_impl!(u8, i8);
|
||||
primitive_cast_impl!(u8, u64);
|
||||
primitive_cast_impl!(u8, u32);
|
||||
primitive_cast_impl!(u8, u16);
|
||||
primitive_cast_impl!(u8, u8);
|
||||
primitive_cast_impl!(u8, isize);
|
||||
primitive_cast_impl!(u8, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(u32, f64, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, f32, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, i64, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, i32, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, i16, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, i8, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, u64, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, u32, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, u16, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, u8, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, isize, u32Cast);
|
||||
primitive_double_dispatch_cast_impl!(u32, usize, u32Cast);
|
||||
primitive_cast_impl!(usize, f64);
|
||||
primitive_cast_impl!(usize, f32);
|
||||
primitive_cast_impl!(usize, i64);
|
||||
primitive_cast_impl!(usize, i32);
|
||||
primitive_cast_impl!(usize, i16);
|
||||
primitive_cast_impl!(usize, i8);
|
||||
primitive_cast_impl!(usize, u64);
|
||||
primitive_cast_impl!(usize, u32);
|
||||
primitive_cast_impl!(usize, u16);
|
||||
primitive_cast_impl!(usize, u8);
|
||||
primitive_cast_impl!(usize, isize);
|
||||
primitive_cast_impl!(usize, usize);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(u16, f64, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, f32, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, i64, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, i32, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, i16, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, i8, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, u64, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, u32, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, u16, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, u8, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, isize, u16Cast);
|
||||
primitive_double_dispatch_cast_impl!(u16, usize, u16Cast);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(u8, f64, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, f32, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, i64, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, i32, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, i16, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, i8, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, u64, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, u32, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, u16, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, u8, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, isize, u8Cast);
|
||||
primitive_double_dispatch_cast_impl!(u8, usize, u8Cast);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(usize, f64, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, f32, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, i64, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, i32, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, i16, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, i8, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, u64, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, u32, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, u16, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, u8, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, isize, usizeCast);
|
||||
primitive_double_dispatch_cast_impl!(usize, usize, usizeCast);
|
||||
|
||||
primitive_double_dispatch_cast_impl!(isize, f64, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, f32, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, i64, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, i32, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, i16, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, i8, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, u64, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, u32, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, u16, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, u8, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, isize, isizeCast);
|
||||
primitive_double_dispatch_cast_impl!(isize, usize, isizeCast);
|
||||
primitive_cast_impl!(isize, f64);
|
||||
primitive_cast_impl!(isize, f32);
|
||||
primitive_cast_impl!(isize, i64);
|
||||
primitive_cast_impl!(isize, i32);
|
||||
primitive_cast_impl!(isize, i16);
|
||||
primitive_cast_impl!(isize, i8);
|
||||
primitive_cast_impl!(isize, u64);
|
||||
primitive_cast_impl!(isize, u32);
|
||||
primitive_cast_impl!(isize, u16);
|
||||
primitive_cast_impl!(isize, u8);
|
||||
primitive_cast_impl!(isize, isize);
|
||||
primitive_cast_impl!(isize, usize);
|
||||
|
@ -1,257 +0,0 @@
|
||||
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
use traits::operations::ApproxEq;
|
||||
use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim, Shape, BaseFloat, BaseNum, Bounded};
|
||||
use traits::geometry::{Translation, Dot, Norm};
|
||||
use structs::vec;
|
||||
|
||||
impl<N> Zero for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn zero() -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Index<usize> for vec::Vec0<N> {
|
||||
type Output = N;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, _: usize) -> &N {
|
||||
panic!("Canot index a Vec0.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> IndexMut<usize> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, _: usize) -> &mut N {
|
||||
panic!("Canot index a Vec0.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Shape<usize> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn shape(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Indexable<usize, N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn swap(&mut self, _: usize, _: usize) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, _: usize) -> N {
|
||||
panic!("Cannot index a Vec0.")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, _: usize, _: N) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: 'static> Iterable<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N> {
|
||||
unsafe { mem::transmute::<&'l vec::Vec0<N>, &'l [N; 0]>(self).iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: 'static> IterableMut<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
|
||||
unsafe { mem::transmute::<&'l mut vec::Vec0<N>, &'l mut [N; 0]>(self).iter_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Dim for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn dim(_: Option<vec::Vec0<N>>) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Basis for vec::Vec0<N> {
|
||||
#[inline(always)]
|
||||
fn canonical_basis<F: FnMut(vec::Vec0<N>) -> bool>(_: F) { }
|
||||
|
||||
#[inline(always)]
|
||||
fn orthonormal_subspace_basis<F: FnMut(vec::Vec0<N>) -> bool>(_: &vec::Vec0<N>, _: F) { }
|
||||
|
||||
#[inline(always)]
|
||||
fn canonical_basis_element(_: usize) -> Option<vec::Vec0<N>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T> Add<T> for vec::Vec0<N> {
|
||||
type Output = vec::Vec0<N>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, _: T) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T> Sub<T> for vec::Vec0<N> {
|
||||
type Output = vec::Vec0<N>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, _: T) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<Output = N> + Copy> Neg for vec::Vec0<N> {
|
||||
type Output = vec::Vec0<N>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum> Dot<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn dot(&self, _: &vec::Vec0<N>) -> N {
|
||||
::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T> Mul<T> for vec::Vec0<N> {
|
||||
type Output = vec::Vec0<N>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, _: T) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T> Div<T> for vec::Vec0<N> {
|
||||
type Output = vec::Vec0<N>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, _: T) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Neg<Output = N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn translation(&self) -> vec::Vec0<N> {
|
||||
*self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inv_translation(&self) -> vec::Vec0<N> {
|
||||
-*self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_translation_mut(&mut self, t: &vec::Vec0<N>) {
|
||||
*self = *t + *self;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn append_translation(&self, t: &vec::Vec0<N>) -> vec::Vec0<N> {
|
||||
*t + self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_translation_mut(&mut self, t: &vec::Vec0<N>) {
|
||||
*self = *self + *t;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prepend_translation(&self, t: &vec::Vec0<N>) -> vec::Vec0<N> {
|
||||
*self + *t
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_translation(&mut self, _: vec::Vec0<N>) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat> Norm<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N {
|
||||
::zero()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm(&self) -> N {
|
||||
::zero()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&self) -> vec::Vec0<N> {
|
||||
::zero()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_mut(&mut self) -> N {
|
||||
::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N>> ApproxEq<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<vec::Vec0<N>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
fn approx_ulps(_: Option<vec::Vec0<N>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, _: &vec::Vec0<N>, _: &N) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, _: &vec::Vec0<N>, _: u32) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: One> One for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn one() -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> FromIterator<N> for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item = N>>(_: I) -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Bounded> Bounded for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn max_value() -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_value() -> vec::Vec0<N> {
|
||||
vec::Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Rand for vec::Vec0<N> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(_: &mut R) -> vec::Vec0<N> { vec::Vec0(PhantomData) }
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
//! Vectors with dimensions known at compile-time.
|
||||
|
||||
#![allow(missing_docs)] // we allow missing to avoid having to document the dispatch traits.
|
||||
//! Vectors with dimension known at compile-time.
|
||||
|
||||
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::iter::{Iterator, FromIterator, IntoIterator};
|
||||
use std::fmt;
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
use traits::operations::{ApproxEq, POrd, POrdering, Axpy, Absolute, Mean};
|
||||
@ -20,27 +18,10 @@ use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6};
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
|
||||
/// Vector of dimension 0.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||
pub struct Vec0<N>(pub PhantomData<N>);
|
||||
|
||||
impl<N> Vec0<N> {
|
||||
/// Creates a new vector.
|
||||
#[inline]
|
||||
pub fn new() -> Vec0<N> {
|
||||
Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> Repeat<N> for Vec0<N> {
|
||||
#[inline]
|
||||
fn repeat(_: N) -> Vec0<N> {
|
||||
Vec0(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector of dimension 1.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec1<N> {
|
||||
@ -49,7 +30,7 @@ pub struct Vec1<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec1, x);
|
||||
ord_impl!(Vec1, x,);
|
||||
pord_impl!(Vec1, x,);
|
||||
vec_axis_impl!(Vec1, x);
|
||||
vec_cast_impl!(Vec1, x);
|
||||
conversion_impl!(Vec1, 1);
|
||||
@ -91,8 +72,12 @@ absolute_vec_impl!(Vec1, x);
|
||||
arbitrary_impl!(Vec1, x);
|
||||
rand_impl!(Vec1, x);
|
||||
mean_impl!(Vec1);
|
||||
vec_display_impl!(Vec1);
|
||||
|
||||
/// Vector of dimension 2.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec2<N> {
|
||||
@ -103,7 +88,7 @@ pub struct Vec2<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec2, x, y);
|
||||
ord_impl!(Vec2, x, y);
|
||||
pord_impl!(Vec2, x, y);
|
||||
vec_axis_impl!(Vec2, x, y);
|
||||
vec_cast_impl!(Vec2, x, y);
|
||||
conversion_impl!(Vec2, 2);
|
||||
@ -145,8 +130,12 @@ absolute_vec_impl!(Vec2, x, y);
|
||||
arbitrary_impl!(Vec2, x, y);
|
||||
rand_impl!(Vec2, x, y);
|
||||
mean_impl!(Vec2);
|
||||
vec_display_impl!(Vec2);
|
||||
|
||||
/// Vector of dimension 3.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec3<N> {
|
||||
@ -159,7 +148,7 @@ pub struct Vec3<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec3, x, y, z);
|
||||
ord_impl!(Vec3, x, y, z);
|
||||
pord_impl!(Vec3, x, y, z);
|
||||
vec_axis_impl!(Vec3, x, y, z);
|
||||
vec_cast_impl!(Vec3, x, y, z);
|
||||
conversion_impl!(Vec3, 3);
|
||||
@ -201,9 +190,13 @@ absolute_vec_impl!(Vec3, x, y, z);
|
||||
arbitrary_impl!(Vec3, x, y, z);
|
||||
rand_impl!(Vec3, x, y, z);
|
||||
mean_impl!(Vec3);
|
||||
vec_display_impl!(Vec3);
|
||||
|
||||
|
||||
/// Vector of dimension 4.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec4<N> {
|
||||
@ -218,7 +211,7 @@ pub struct Vec4<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec4, x, y, z, w);
|
||||
ord_impl!(Vec4, x, y, z, w);
|
||||
pord_impl!(Vec4, x, y, z, w);
|
||||
vec_axis_impl!(Vec4, x, y, z, w);
|
||||
vec_cast_impl!(Vec4, x, y, z, w);
|
||||
conversion_impl!(Vec4, 4);
|
||||
@ -260,8 +253,12 @@ absolute_vec_impl!(Vec4, x, y, z, w);
|
||||
arbitrary_impl!(Vec4, x, y, z, w);
|
||||
rand_impl!(Vec4, x, y, z, w);
|
||||
mean_impl!(Vec4);
|
||||
vec_display_impl!(Vec4);
|
||||
|
||||
/// Vector of dimension 5.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec5<N> {
|
||||
@ -278,7 +275,7 @@ pub struct Vec5<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec5, x, y, z, w, a);
|
||||
ord_impl!(Vec5, x, y, z, w, a);
|
||||
pord_impl!(Vec5, x, y, z, w, a);
|
||||
vec_axis_impl!(Vec5, x, y, z, w, a);
|
||||
vec_cast_impl!(Vec5, x, y, z, w, a);
|
||||
conversion_impl!(Vec5, 5);
|
||||
@ -320,8 +317,12 @@ absolute_vec_impl!(Vec5, x, y, z, w, a);
|
||||
arbitrary_impl!(Vec5, x, y, z, w, a);
|
||||
rand_impl!(Vec5, x, y, z, w, a);
|
||||
mean_impl!(Vec5);
|
||||
vec_display_impl!(Vec5);
|
||||
|
||||
/// Vector of dimension 6.
|
||||
///
|
||||
/// The main differance between a point and a vector is that a vector is not affected by
|
||||
/// translations.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Hash, Debug, Copy)]
|
||||
pub struct Vec6<N> {
|
||||
@ -340,7 +341,7 @@ pub struct Vec6<N> {
|
||||
}
|
||||
|
||||
new_impl!(Vec6, x, y, z, w, a, b);
|
||||
ord_impl!(Vec6, x, y, z, w, a, b);
|
||||
pord_impl!(Vec6, x, y, z, w, a, b);
|
||||
vec_axis_impl!(Vec6, x, y, z, w, a, b);
|
||||
vec_cast_impl!(Vec6, x, y, z, w, a, b);
|
||||
conversion_impl!(Vec6, 6);
|
||||
@ -380,3 +381,4 @@ absolute_vec_impl!(Vec6, x, y, z, w, a, b);
|
||||
arbitrary_impl!(Vec6, x, y, z, w, a, b);
|
||||
rand_impl!(Vec6, x, y, z, w, a, b);
|
||||
mean_impl!(Vec6);
|
||||
vec_display_impl!(Vec6);
|
||||
|
@ -74,7 +74,7 @@ macro_rules! at_fast_impl(
|
||||
|
||||
// FIXME: N should be bounded by Ord instead of BaseFloat…
|
||||
// However, f32/f64 does not implement Ord…
|
||||
macro_rules! ord_impl(
|
||||
macro_rules! pord_impl(
|
||||
($t: ident, $comp0: ident, $($compN: ident),*) => (
|
||||
impl<N: BaseFloat> POrd for $t<N> {
|
||||
#[inline]
|
||||
@ -278,6 +278,7 @@ macro_rules! dim_impl(
|
||||
macro_rules! container_impl(
|
||||
($t: ident) => (
|
||||
impl<N> $t<N> {
|
||||
/// The dimension of this entity.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
Dim::dim(None::<$t<N>>)
|
||||
@ -291,18 +292,18 @@ macro_rules! basis_impl(
|
||||
impl<N: BaseFloat + ApproxEq<N>> Basis for $t<N> {
|
||||
#[inline]
|
||||
fn canonical_basis<F: FnMut($t<N>) -> bool>(mut f: F) {
|
||||
for i in 0..$dim {
|
||||
for i in 0 .. $dim {
|
||||
if !f(Basis::canonical_basis_element(i).unwrap()) { return }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn orthonormal_subspace_basis<F: FnMut($t<N>) -> bool>(n: &$t<N>, mut f: F) {
|
||||
// compute the basis of the orthogonal subspace using Gram-Schmidt
|
||||
// orthogonalization algorithm
|
||||
// Compute the basis of the orthogonal subspace using Gram-Schmidt
|
||||
// orthogonalization algorithm.
|
||||
let mut basis: Vec<$t<N>> = Vec::new();
|
||||
|
||||
for i in 0..$dim {
|
||||
for i in 0 .. $dim {
|
||||
let mut basis_element : $t<N> = ::zero();
|
||||
|
||||
unsafe {
|
||||
@ -743,6 +744,7 @@ macro_rules! transform_impl(
|
||||
macro_rules! vec_as_pnt_impl(
|
||||
($tv: ident, $t: ident, $($compN: ident),+) => (
|
||||
impl<N> $tv<N> {
|
||||
/// Converts this vector to a point.
|
||||
#[inline]
|
||||
pub fn to_pnt(self) -> $t<N> {
|
||||
$t::new(
|
||||
@ -750,6 +752,7 @@ macro_rules! vec_as_pnt_impl(
|
||||
)
|
||||
}
|
||||
|
||||
/// Reinterprets this vector as a point.
|
||||
#[inline]
|
||||
pub fn as_pnt(&self) -> &$t<N> {
|
||||
unsafe {
|
||||
@ -817,3 +820,25 @@ macro_rules! mean_impl(
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
macro_rules! vec_display_impl(
|
||||
($t: ident) => (
|
||||
impl<N: fmt::Display> fmt::Display for $t<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "("));
|
||||
|
||||
let mut it = self.iter();
|
||||
|
||||
let precision = f.precision().unwrap_or(8);
|
||||
|
||||
try!(write!(f, "{:.*}", precision, *it.next().unwrap()));
|
||||
|
||||
for comp in it {
|
||||
try!(write!(f, ", {:.*}", precision, *comp));
|
||||
}
|
||||
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
123
src/structs/vecn.rs
Normal file
123
src/structs/vecn.rs
Normal file
@ -0,0 +1,123 @@
|
||||
use std::slice::{Iter, IterMut};
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
|
||||
use std::mem;
|
||||
use rand::{Rand, Rng};
|
||||
use num::{Zero, One};
|
||||
use generic_array::{GenericArray, ArrayLength};
|
||||
use traits::operations::{ApproxEq, Axpy, Mean};
|
||||
use traits::geometry::{Dot, Norm};
|
||||
use traits::structure::{Iterable, IterableMut, Indexable, Shape, BaseFloat, BaseNum, Cast, Dim};
|
||||
#[cfg(feature="arbitrary")]
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
/// A static array of arbitrary dimension.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, PartialEq, Debug)] // FIXME: Hash, RustcEncodable, RustcDecodable
|
||||
pub struct VecN<N, D: ArrayLength<N>> {
|
||||
/// The underlying data of the vector.
|
||||
pub at: GenericArray<N, D>
|
||||
}
|
||||
|
||||
unsafe impl<N: Send, D: ArrayLength<N>> Send for VecN<N, D> {
|
||||
}
|
||||
|
||||
impl<N: Clone, D: ArrayLength<N>> Clone for VecN<N, D> {
|
||||
fn clone(&self) -> VecN<N, D> {
|
||||
VecN::new(self.at.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy, D: ArrayLength<N>> Copy for VecN<N, D>
|
||||
where D::ArrayType: Copy { }
|
||||
|
||||
impl<N, D: ArrayLength<N>> VecN<N, D> {
|
||||
/// Creates a new vector from a given arbirtarily-sized array.
|
||||
#[inline]
|
||||
pub fn new(components: GenericArray<N, D>) -> VecN<N, D> {
|
||||
VecN {
|
||||
at: components
|
||||
}
|
||||
}
|
||||
|
||||
/// The vector length.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.at.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, D: ArrayLength<N>> Dim for VecN<N, D> {
|
||||
fn dim(_unused: Option<Self>) -> usize {
|
||||
D::to_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy, D: ArrayLength<N>> FromIterator<N> for VecN<N, D> {
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item = N>>(param: I) -> VecN<N, D> {
|
||||
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
|
||||
|
||||
let mut it = param.into_iter();
|
||||
|
||||
for e in res.iter_mut() {
|
||||
*e = it.next().expect("Not enough data into the provided iterator to initialize this `VecN`.");
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Rand + Zero, D: ArrayLength<N>> Rand for VecN<N, D> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> VecN<N, D> {
|
||||
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
|
||||
|
||||
for e in res.iter_mut() {
|
||||
*e = Rand::rand(rng)
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + One + Zero, D: ArrayLength<N>> One for VecN<N, D> {
|
||||
#[inline]
|
||||
fn one() -> VecN<N, D> {
|
||||
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
|
||||
|
||||
for e in res.iter_mut() {
|
||||
*e = ::one()
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Zero, D: ArrayLength<N>> Zero for VecN<N, D> {
|
||||
#[inline]
|
||||
fn zero() -> VecN<N, D> {
|
||||
let mut res: VecN<N, D> = unsafe { mem::uninitialized() };
|
||||
|
||||
for e in res.iter_mut() {
|
||||
*e = ::zero()
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
self.iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="arbitrary")]
|
||||
impl<N: Arbitrary + Zero + Copy, D: 'static + ArrayLength<N>> Arbitrary for VecN<N, D> {
|
||||
#[inline]
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> VecN<N, D> {
|
||||
(0 .. D::to_usize()).map(|_| Arbitrary::arbitrary(g)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
vecn_dvec_common_impl!(VecN, D);
|
312
src/structs/vecn_macros.rs
Normal file
312
src/structs/vecn_macros.rs
Normal file
@ -0,0 +1,312 @@
|
||||
#![macro_use]
|
||||
|
||||
macro_rules! vecn_dvec_common_impl(
|
||||
($vecn: ident $(, $param: ident)*) => (
|
||||
impl<N: Zero + Copy + Clone $(, $param: ArrayLength<N>)*> $vecn<N $(, $param)*> {
|
||||
/// Tests if all components of the vector are zeroes.
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.as_ref().iter().all(|e| e.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param: ArrayLength<N>)*> AsRef<[N]> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[N] {
|
||||
&self.at[.. self.len()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param: ArrayLength<N>)*> AsMut<[N]> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [N] {
|
||||
let len = self.len();
|
||||
&mut self.at[.. len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param: ArrayLength<N>)*> Shape<usize> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn shape(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy $(, $param : ArrayLength<N>)*> Indexable<usize, N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn swap(&mut self, i: usize, j: usize) {
|
||||
assert!(i < self.len());
|
||||
assert!(j < self.len());
|
||||
self.as_mut().swap(i, j);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_at(&self, i: usize) -> N {
|
||||
*self[..].get_unchecked(i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unsafe_set(&mut self, i: usize, val: N) {
|
||||
*self[..].get_unchecked_mut(i) = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<N, T $(, $param: ArrayLength<N>)*> Index<T> for $vecn<N $(, $param)*> where [N]: Index<T> {
|
||||
type Output = <[N] as Index<T>>::Output;
|
||||
|
||||
fn index(&self, i: T) -> &<[N] as Index<T>>::Output {
|
||||
&self.as_ref()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, T $(, $param: ArrayLength<N>)*> IndexMut<T> for $vecn<N $(, $param)*> where [N]: IndexMut<T> {
|
||||
fn index_mut(&mut self, i: T) -> &mut <[N] as Index<T>>::Output {
|
||||
&mut self.as_mut()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param : ArrayLength<N>)*> Iterable<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn iter<'l>(&'l self) -> Iter<'l, N> {
|
||||
self.as_ref().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N $(, $param : ArrayLength<N>)*> IterableMut<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn iter_mut<'l>(&'l mut self) -> IterMut<'l, N> {
|
||||
self.as_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Mul<N, Output = N> $(, $param : ArrayLength<N>)*>
|
||||
Axpy<N> for $vecn<N $(, $param)*> {
|
||||
fn axpy(&mut self, a: &N, x: &$vecn<N $(, $param)*>) {
|
||||
assert!(self.len() == x.len());
|
||||
|
||||
for i in 0 .. x.len() {
|
||||
unsafe {
|
||||
let self_i = self.unsafe_at(i);
|
||||
self.unsafe_set(i, self_i + *a * x.unsafe_at(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
|
||||
Mul<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left * *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
|
||||
Div<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left / *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
|
||||
Add<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left + *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Sub<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
|
||||
Sub<$vecn<N $(, $param)*>> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: $vecn<N $(, $param)*>) -> $vecn<N $(, $param)*> {
|
||||
assert!(self.len() == right.len());
|
||||
|
||||
let mut res = self;
|
||||
|
||||
for (left, right) in res.as_mut().iter_mut().zip(right.as_ref().iter()) {
|
||||
*left = *left - *right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Neg<Output = N> + Zero + Copy $(, $param : ArrayLength<N>)*> Neg for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn neg(mut self) -> $vecn<N $(, $param)*> {
|
||||
for e in self.as_mut().iter_mut() {
|
||||
*e = -*e;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseNum $(, $param : ArrayLength<N>)*> Dot<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn dot(&self, other: &$vecn<N $(, $param)*>) -> N {
|
||||
assert!(self.len() == other.len());
|
||||
let mut res: N = ::zero();
|
||||
for i in 0 .. self.len() {
|
||||
res = res + unsafe { self.unsafe_at(i) * other.unsafe_at(i) };
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat $(, $param : ArrayLength<N>)*> Norm<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn sqnorm(&self) -> N {
|
||||
Dot::dot(self, self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize(&self) -> $vecn<N $(, $param)*> {
|
||||
let mut res : $vecn<N $(, $param)*> = self.clone();
|
||||
let _ = res.normalize_mut();
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn normalize_mut(&mut self) -> N {
|
||||
let l = Norm::norm(self);
|
||||
|
||||
for n in self.as_mut().iter_mut() {
|
||||
*n = *n / l;
|
||||
}
|
||||
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: BaseFloat + Cast<f64> $(, $param : ArrayLength<N>)*> Mean<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn mean(&self) -> N {
|
||||
let normalizer = ::cast(1.0f64 / self.len() as f64);
|
||||
self.iter().fold(::zero(), |acc, x| acc + *x * normalizer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ApproxEq<N> $(, $param : ArrayLength<N>)*> ApproxEq<N> for $vecn<N $(, $param)*> {
|
||||
#[inline]
|
||||
fn approx_epsilon(_: Option<$vecn<N $(, $param)*>>) -> N {
|
||||
ApproxEq::approx_epsilon(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_ulps(_: Option<$vecn<N $(, $param)*>>) -> u32 {
|
||||
ApproxEq::approx_ulps(None::<N>)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_eps(&self, other: &$vecn<N $(, $param)*>, epsilon: &N) -> bool {
|
||||
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_eps(a, b, epsilon))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn approx_eq_ulps(&self, other: &$vecn<N $(, $param)*>, ulps: u32) -> bool {
|
||||
let mut zip = self.as_ref().iter().zip(other.as_ref().iter());
|
||||
zip.all(|(a, b)| ApproxEq::approx_eq_ulps(a, b, ulps))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Mul<N, Output = N> + Zero $(, $param : ArrayLength<N>)*>
|
||||
Mul<N> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, right: N) -> $vecn<N $(, $param)*> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e * right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Div<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Div<N> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn div(self, right: N) -> $vecn<N $(, $param)*> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e / right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Add<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Add<N> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, right: N) -> $vecn<N $(, $param)*> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e + right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Copy + Sub<N, Output = N> + Zero $(, $param : ArrayLength<N>)*> Sub<N> for $vecn<N $(, $param)*> {
|
||||
type Output = $vecn<N $(, $param)*>;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, right: N) -> $vecn<N $(, $param)*> {
|
||||
let mut res = self;
|
||||
|
||||
for e in res.as_mut().iter_mut() {
|
||||
*e = *e - right
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
@ -158,7 +158,7 @@ pub trait RowSlice<R> {
|
||||
/// Trait of objects having a spacial dimension known at compile time.
|
||||
pub trait Dim: Sized {
|
||||
/// The dimension of the object.
|
||||
fn dim(unused_mut: Option<Self>) -> usize;
|
||||
fn dim(_unused: Option<Self>) -> usize;
|
||||
}
|
||||
|
||||
/// Trait to get the diagonal of square matrices.
|
||||
|
173
tests/mat.rs
173
tests/mat.rs
@ -2,8 +2,8 @@ extern crate nalgebra as na;
|
||||
extern crate rand;
|
||||
|
||||
use rand::random;
|
||||
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot2, Rot3, Persp3, PerspMat3, Ortho3,
|
||||
OrthoMat3, DMat, DVec, Row, Col, BaseFloat, Diag, Transpose, RowSlice, ColSlice, Shape};
|
||||
use na::{Rot2, Rot3, Iso2, Iso3, Sim2, Sim3, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, DMat, DVec,
|
||||
Row, Col, Diag, Transpose, RowSlice, ColSlice, Shape};
|
||||
|
||||
macro_rules! test_inv_mat_impl(
|
||||
($t: ty) => (
|
||||
@ -12,7 +12,9 @@ macro_rules! test_inv_mat_impl(
|
||||
|
||||
match na::inv(&randmat) {
|
||||
None => { },
|
||||
Some(i) => assert!(na::approx_eq(&(i * randmat), &na::one()))
|
||||
Some(i) => {
|
||||
assert!(na::approx_eq(&(i * randmat), &na::one()))
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -183,13 +185,33 @@ fn test_inv_mat6() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rotation2() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let randmat: na::Rot2<f64> = na::one();
|
||||
let ang = Vec1::new(na::abs(&random::<f64>()) % <f64 as BaseFloat>::pi());
|
||||
fn test_inv_rot2() {
|
||||
test_inv_mat_impl!(Rot2<f64>);
|
||||
}
|
||||
|
||||
assert!(na::approx_eq(&na::rotation(&na::append_rotation(&randmat, &ang)), &ang));
|
||||
}
|
||||
#[test]
|
||||
fn test_inv_rot3() {
|
||||
test_inv_mat_impl!(Rot3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_iso2() {
|
||||
test_inv_mat_impl!(Iso2<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_iso3() {
|
||||
test_inv_mat_impl!(Iso3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_sim2() {
|
||||
test_inv_mat_impl!(Sim2<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_sim3() {
|
||||
test_inv_mat_impl!(Sim3<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -199,59 +221,6 @@ fn test_index_mat2() {
|
||||
assert!(mat[(0, 1)] == na::transpose(&mat)[(1, 0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_rotation3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let randmat: Rot3<f64> = na::one();
|
||||
let dir: Vec3<f64> = random();
|
||||
let ang = na::normalize(&dir) * (na::abs(&random::<f64>()) % <f64 as BaseFloat>::pi());
|
||||
let rot = na::append_rotation(&randmat, &ang);
|
||||
|
||||
assert!(na::approx_eq(&(na::transpose(&rot) * rot), &na::one()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot3_rotation_between() {
|
||||
let r1: Rot3<f64> = random();
|
||||
let r2: Rot3<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&(delta * r1), &r2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot3_angle_between() {
|
||||
let r1: Rot3<f64> = random();
|
||||
let r2: Rot3<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
let delta_angle = na::angle_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot2_rotation_between() {
|
||||
let r1: Rot2<f64> = random();
|
||||
let r2: Rot2<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&(delta * r1), &r2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot2_angle_between() {
|
||||
let r1: Rot2<f64> = random();
|
||||
let r2: Rot2<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
let delta_angle = na::angle_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mean_dmat() {
|
||||
@ -755,86 +724,6 @@ fn test_row_3() {
|
||||
assert!(second_col == Vec3::new(1.0, 4.0, 7.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_persp() {
|
||||
let mut p = Persp3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
let mut pm = PerspMat3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
assert!(p.to_mat() == pm.to_mat());
|
||||
assert!(p.aspect() == 42.0);
|
||||
assert!(p.fov() == 0.5);
|
||||
assert!(p.znear() == 1.5);
|
||||
assert!(p.zfar() == 10.0);
|
||||
assert!(na::approx_eq(&pm.aspect(), &42.0));
|
||||
assert!(na::approx_eq(&pm.fov(), &0.5));
|
||||
assert!(na::approx_eq(&pm.znear(), &1.5));
|
||||
assert!(na::approx_eq(&pm.zfar(), &10.0));
|
||||
|
||||
p.set_fov(0.1);
|
||||
pm.set_fov(0.1);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_znear(24.0);
|
||||
pm.set_znear(24.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_zfar(61.0);
|
||||
pm.set_zfar(61.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_aspect(23.0);
|
||||
pm.set_aspect(23.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
assert!(p.aspect() == 23.0);
|
||||
assert!(p.fov() == 0.1);
|
||||
assert!(p.znear() == 24.0);
|
||||
assert!(p.zfar() == 61.0);
|
||||
assert!(na::approx_eq(&pm.aspect(), &23.0));
|
||||
assert!(na::approx_eq(&pm.fov(), &0.1));
|
||||
assert!(na::approx_eq(&pm.znear(), &24.0));
|
||||
assert!(na::approx_eq(&pm.zfar(), &61.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ortho() {
|
||||
let mut p = Ortho3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
let mut pm = OrthoMat3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
assert!(p.to_mat() == pm.to_mat());
|
||||
assert!(p.width() == 42.0);
|
||||
assert!(p.height() == 0.5);
|
||||
assert!(p.znear() == 1.5);
|
||||
assert!(p.zfar() == 10.0);
|
||||
assert!(na::approx_eq(&pm.width(), &42.0));
|
||||
assert!(na::approx_eq(&pm.height(), &0.5));
|
||||
assert!(na::approx_eq(&pm.znear(), &1.5));
|
||||
assert!(na::approx_eq(&pm.zfar(), &10.0));
|
||||
|
||||
p.set_width(0.1);
|
||||
pm.set_width(0.1);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_znear(24.0);
|
||||
pm.set_znear(24.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_zfar(61.0);
|
||||
pm.set_zfar(61.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_height(23.0);
|
||||
pm.set_height(23.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
assert!(p.height() == 23.0);
|
||||
assert!(p.width() == 0.1);
|
||||
assert!(p.znear() == 24.0);
|
||||
assert!(p.zfar() == 61.0);
|
||||
assert!(na::approx_eq(&pm.height(), &23.0));
|
||||
assert!(na::approx_eq(&pm.width(), &0.1));
|
||||
assert!(na::approx_eq(&pm.znear(), &24.0));
|
||||
assert!(na::approx_eq(&pm.zfar(), &61.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cholesky_const() {
|
||||
|
||||
|
280
tests/transforms.rs
Normal file
280
tests/transforms.rs
Normal file
@ -0,0 +1,280 @@
|
||||
extern crate nalgebra as na;
|
||||
extern crate rand;
|
||||
|
||||
use rand::random;
|
||||
use na::{Pnt2, Pnt3, Vec2, Vec3, Vec1, Rot2, Rot3, Persp3, PerspMat3, Ortho3, OrthoMat3,
|
||||
Iso2, Iso3, Sim2, Sim3, BaseFloat, Transform};
|
||||
|
||||
#[test]
|
||||
fn test_rotation2() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let randmat: na::Rot2<f64> = na::one();
|
||||
let ang = Vec1::new(na::abs(&random::<f64>()) % <f64 as BaseFloat>::pi());
|
||||
|
||||
assert!(na::approx_eq(&na::rotation(&na::append_rotation(&randmat, &ang)), &ang));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_rotation3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let randmat: Rot3<f64> = na::one();
|
||||
let dir: Vec3<f64> = random();
|
||||
let ang = na::normalize(&dir) * (na::abs(&random::<f64>()) % <f64 as BaseFloat>::pi());
|
||||
let rot = na::append_rotation(&randmat, &ang);
|
||||
|
||||
assert!(na::approx_eq(&(na::transpose(&rot) * rot), &na::one()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot3_rotation_between() {
|
||||
let r1: Rot3<f64> = random();
|
||||
let r2: Rot3<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&(delta * r1), &r2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot3_angle_between() {
|
||||
let r1: Rot3<f64> = random();
|
||||
let r2: Rot3<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
let delta_angle = na::angle_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot2_rotation_between() {
|
||||
let r1: Rot2<f64> = random();
|
||||
let r2: Rot2<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&(delta * r1), &r2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rot2_angle_between() {
|
||||
let r1: Rot2<f64> = random();
|
||||
let r2: Rot2<f64> = random();
|
||||
|
||||
let delta = na::rotation_between(&r1, &r2);
|
||||
let delta_angle = na::angle_between(&r1, &r2);
|
||||
|
||||
assert!(na::approx_eq(&na::norm(&na::rotation(&delta)), &delta_angle))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_look_at_rh_iso3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let eye = random::<Pnt3<f64>>();
|
||||
let target = random::<Pnt3<f64>>();
|
||||
let up = random::<Vec3<f64>>();
|
||||
let viewmat = Iso3::look_at_rh(&eye, &target, &up);
|
||||
|
||||
let origin: Pnt3<f64> = na::orig();
|
||||
assert_eq!(&(viewmat * eye), &origin);
|
||||
assert!(na::approx_eq(&na::normalize(&(viewmat * (target - eye))), &-Vec3::z()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_look_at_rh_rot3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let dir = random::<Vec3<f64>>();
|
||||
let up = random::<Vec3<f64>>();
|
||||
let viewmat = Rot3::look_at_rh(&dir, &up);
|
||||
|
||||
println!("found: {}", viewmat * dir);
|
||||
assert!(na::approx_eq(&na::normalize(&(viewmat * dir)), &-Vec3::z()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_observer_frame_iso3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let eye = random::<Pnt3<f64>>();
|
||||
let target = random::<Pnt3<f64>>();
|
||||
let up = random::<Vec3<f64>>();
|
||||
let observer = Iso3::new_observer_frame(&eye, &target, &up);
|
||||
|
||||
assert_eq!(&(observer * na::orig::<Pnt3<f64>>()), &eye);
|
||||
assert!(na::approx_eq(&(observer * Vec3::z()), &na::normalize(&(target - eye))));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_observer_frame_rot3() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let dir = random::<Vec3<f64>>();
|
||||
let up = random::<Vec3<f64>>();
|
||||
let observer = Rot3::new_observer_frame(&dir, &up);
|
||||
|
||||
assert!(na::approx_eq(&(observer * Vec3::z()), &na::normalize(&dir)));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_persp() {
|
||||
let mut p = Persp3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
let mut pm = PerspMat3::new(42.0f64, 0.5, 1.5, 10.0);
|
||||
assert!(p.to_mat() == pm.to_mat());
|
||||
assert!(p.aspect() == 42.0);
|
||||
assert!(p.fovy() == 0.5);
|
||||
assert!(p.znear() == 1.5);
|
||||
assert!(p.zfar() == 10.0);
|
||||
assert!(na::approx_eq(&pm.aspect(), &42.0));
|
||||
assert!(na::approx_eq(&pm.fovy(), &0.5));
|
||||
assert!(na::approx_eq(&pm.znear(), &1.5));
|
||||
assert!(na::approx_eq(&pm.zfar(), &10.0));
|
||||
|
||||
p.set_fovy(0.1);
|
||||
pm.set_fovy(0.1);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_znear(24.0);
|
||||
pm.set_znear(24.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_zfar(61.0);
|
||||
pm.set_zfar(61.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_aspect(23.0);
|
||||
pm.set_aspect(23.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
assert!(p.aspect() == 23.0);
|
||||
assert!(p.fovy() == 0.1);
|
||||
assert!(p.znear() == 24.0);
|
||||
assert!(p.zfar() == 61.0);
|
||||
assert!(na::approx_eq(&pm.aspect(), &23.0));
|
||||
assert!(na::approx_eq(&pm.fovy(), &0.1));
|
||||
assert!(na::approx_eq(&pm.znear(), &24.0));
|
||||
assert!(na::approx_eq(&pm.zfar(), &61.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ortho() {
|
||||
let mut p = Ortho3::new(-0.3, 5.2, -3.9, -1.0, 1.5, 10.0);
|
||||
let mut pm = OrthoMat3::new(-0.3, 5.2, -3.9, -1.0, 1.5, 10.0);
|
||||
assert!(p.to_mat() == pm.to_mat());
|
||||
assert!(p.left() == -0.3);
|
||||
assert!(p.right() == 5.2);
|
||||
assert!(p.bottom() == -3.9);
|
||||
assert!(p.top() == -1.0);
|
||||
assert!(p.znear() == 1.5);
|
||||
assert!(p.zfar() == 10.0);
|
||||
assert!(na::approx_eq(&pm.left(), &-0.3));
|
||||
assert!(na::approx_eq(&pm.right(), &5.2));
|
||||
assert!(na::approx_eq(&pm.bottom(), &-3.9));
|
||||
assert!(na::approx_eq(&pm.top(), &-1.0));
|
||||
assert!(na::approx_eq(&pm.znear(), &1.5));
|
||||
assert!(na::approx_eq(&pm.zfar(), &10.0));
|
||||
|
||||
p.set_left(0.1);
|
||||
pm.set_left(0.1);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_right(10.1);
|
||||
pm.set_right(10.1);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_top(24.0);
|
||||
pm.set_top(24.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_bottom(-23.0);
|
||||
pm.set_bottom(-23.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_zfar(61.0);
|
||||
pm.set_zfar(61.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
p.set_znear(21.0);
|
||||
pm.set_znear(21.0);
|
||||
assert!(na::approx_eq(&p.to_mat(), pm.as_mat()));
|
||||
|
||||
assert!(p.znear() == 21.0);
|
||||
assert!(p.zfar() == 61.0);
|
||||
assert!(na::approx_eq(&pm.znear(), &21.0));
|
||||
assert!(na::approx_eq(&pm.zfar(), &61.0));
|
||||
}
|
||||
|
||||
macro_rules! test_transform_inv_transform_impl(
|
||||
($fnname: ident, $t: ty, $p: ty) => (
|
||||
#[test]
|
||||
fn $fnname() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let randmat: $t = random();
|
||||
let expected: $p = random();
|
||||
|
||||
let computed = randmat.inv_transform(&randmat.transform(&expected));
|
||||
println!("computed: {}, expected: {}", computed, expected);
|
||||
|
||||
assert!(na::approx_eq(&computed, &expected));
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_rot2, Rot2<f64>, Pnt2<f64>);
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_rot3, Rot3<f64>, Pnt3<f64>);
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_iso2, Iso2<f64>, Pnt2<f64>);
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_iso3, Iso3<f64>, Pnt3<f64>);
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_sim2, Sim2<f64>, Pnt2<f64>);
|
||||
test_transform_inv_transform_impl!(test_transform_inv_transform_sim3, Sim3<f64>, Pnt3<f64>);
|
||||
|
||||
macro_rules! test_transform_mul_assoc(
|
||||
($fnname: ident, $t1: ty, $t2: ty, $p: ty) => (
|
||||
#[test]
|
||||
fn $fnname() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let t1: $t1 = random();
|
||||
let t2: $t2 = random();
|
||||
let p: $p = random();
|
||||
|
||||
let t1p = t1 * p;
|
||||
let t2p = t2 * p;
|
||||
let t1t2 = t1 * t2;
|
||||
let t2t1 = t2 * t1;
|
||||
|
||||
assert!(na::approx_eq(&(t1t2 * p), &(t1 * t2p)));
|
||||
assert!(na::approx_eq(&(t2t1 * p), &(t2 * t1p)));
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_sim3_pnt3, Sim3<f64>, Sim3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_iso3_pnt3, Sim3<f64>, Iso3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_rot3_pnt3, Sim3<f64>, Rot3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso3_iso3_pnt3, Iso3<f64>, Iso3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso3_rot3_pnt3, Iso3<f64>, Rot3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_rot3_rot3_pnt3, Rot3<f64>, Rot3<f64>, Pnt3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_sim3_vec3, Sim3<f64>, Sim3<f64>, Vec3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_iso3_vec3, Sim3<f64>, Iso3<f64>, Vec3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim3_rot3_vec3, Sim3<f64>, Rot3<f64>, Vec3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso3_iso3_vec3, Iso3<f64>, Iso3<f64>, Vec3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso3_rot3_vec3, Iso3<f64>, Rot3<f64>, Vec3<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_rot3_rot3_vec3, Rot3<f64>, Rot3<f64>, Vec3<f64>);
|
||||
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_sim2_pnt2, Sim2<f64>, Sim2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_iso2_pnt2, Sim2<f64>, Iso2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_rot2_pnt2, Sim2<f64>, Rot2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso2_iso2_pnt2, Iso2<f64>, Iso2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso2_rot2_pnt2, Iso2<f64>, Rot2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_rot2_rot2_pnt2, Rot2<f64>, Rot2<f64>, Pnt2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_sim2_vec2, Sim2<f64>, Sim2<f64>, Vec2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_iso2_vec2, Sim2<f64>, Iso2<f64>, Vec2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_sim2_rot2_vec2, Sim2<f64>, Rot2<f64>, Vec2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso2_iso2_vec2, Iso2<f64>, Iso2<f64>, Vec2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_iso2_rot2_vec2, Iso2<f64>, Rot2<f64>, Vec2<f64>);
|
||||
test_transform_mul_assoc!(test_transform_inv_transform_rot2_rot2_vec2, Rot2<f64>, Rot2<f64>, Vec2<f64>);
|
47
tests/vec.rs
47
tests/vec.rs
@ -1,8 +1,16 @@
|
||||
extern crate nalgebra as na;
|
||||
extern crate rand;
|
||||
#[cfg(feature="generic_sizes")]
|
||||
extern crate typenum;
|
||||
extern crate nalgebra as na;
|
||||
|
||||
use rand::random;
|
||||
use na::{Vec0, Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Mat3, Rot2, Rot3, Iterable, IterableMut};
|
||||
use na::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Mat3, Rot2, Rot3, Iterable, IterableMut};
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
use typenum::U10;
|
||||
#[cfg(feature="generic_sizes")]
|
||||
use na::VecN;
|
||||
|
||||
|
||||
macro_rules! test_iterator_impl(
|
||||
($t: ty, $n: ty) => (
|
||||
@ -110,11 +118,6 @@ fn test_cross_vec3() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_commut_dot_vec0() {
|
||||
test_commut_dot_impl!(Vec0<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_commut_dot_vec1() {
|
||||
test_commut_dot_impl!(Vec1<f64>);
|
||||
@ -145,11 +148,6 @@ fn test_commut_dot_vec6() {
|
||||
test_commut_dot_impl!(Vec6<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basis_vec0() {
|
||||
test_basis_impl!(Vec0<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basis_vec1() {
|
||||
test_basis_impl!(Vec1<f64>);
|
||||
@ -180,11 +178,6 @@ fn test_basis_vec6() {
|
||||
test_basis_impl!(Vec6<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subspace_basis_vec0() {
|
||||
test_subspace_basis_impl!(Vec0<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subspace_basis_vec1() {
|
||||
test_subspace_basis_impl!(Vec1<f64>);
|
||||
@ -215,11 +208,6 @@ fn test_subspace_basis_vec6() {
|
||||
test_subspace_basis_impl!(Vec6<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scalar_op_vec0() {
|
||||
test_scalar_op_impl!(Vec0<f64>, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scalar_op_vec1() {
|
||||
test_scalar_op_impl!(Vec1<f64>, f64);
|
||||
@ -250,11 +238,6 @@ fn test_scalar_op_vec6() {
|
||||
test_scalar_op_impl!(Vec6<f64>, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_vec0() {
|
||||
test_iterator_impl!(Vec0<f64>, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_vec1() {
|
||||
test_iterator_impl!(Vec1<f64>, f64);
|
||||
@ -318,6 +301,16 @@ fn test_outer_vec3() {
|
||||
12.0, 15.0, 18.0));
|
||||
}
|
||||
|
||||
#[cfg(feature="generic_sizes")]
|
||||
#[test]
|
||||
fn test_vecn10_add_mul() {
|
||||
for _ in 0usize .. 10000 {
|
||||
let v1: VecN<f64, U10> = random();
|
||||
|
||||
assert!(na::approx_eq(&(v1 + v1), &(v1 * 2.0)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_vec3_rotation_between() {
|
||||
|
Loading…
Reference in New Issue
Block a user