0%

Eigen Tutorial

Eigen is a very versatile library in C++ that helps to solve matrix-related problems in efficient approaches. The functions it supports includes but not limited to:

  • Process arbitrary fixed-size or dynamic-size (unknown in compile-time) dense matrices and sparse matrices of all standard numeric types.
  • Perform matrix decompositions and geometry transforms.
  • Other extendable modules like non-linear optimization, a polynomial solver, FFT etc.

For further details, please visit http://eigen.tuxfamily.org/dox/

Installation

Eigen is a header-only library. There is only two steps before using it:

  1. Download the latest released package
  2. Unzip, and add the path into include directory

A library is called header-only if the full definitions of all macros, functions and classes comprising the library are visible to the compiler in a header file form.

Modules and Headers

Module Header File Contents
Core <Eigen/Core> Definition of Matrix and Array classes; basic linear algebra operations, and array manipulation
Geometry <Eigen/Geometry> Geometry-featured transformations
LU <Eigen/LU> Inverse, determinant, LU decompositions
Cholesky <Eigen/Cholesky> LLT and LDLT Cholesky factorization
Householder <Eigen/Householder> Householder transformations
SVD <Eigen/SVD> SVD decompositions with least-squares solver
QR <Eigen/QR> QR decomposition
Eigenvalues Eigenvalue, eigenvector decompositions
Sparse <Eigen/Sparse> Sparse matrix storage and its basic linear algebra

A Householder transformation (also called Householder reflection or elementary reflector) is a linear transformation that describes a reflection about a plane or hyperplane containing the origin

There are two all-in-one headers that commonly used by developers for convenience. Depending on the context, one may choose:

  • <Eigen/Dense>: Core, Geometry, LU, Cholesky, SVD, QR, and Eigenvalues
  • <Eigen/Eigen>: Dense and Sparse (the whole library)

Matrix Class

Dense and Sparse Matrix

Dense matrix is the commonly used in most cases, which stores whole matrix in memory.

Under some contexts, for example finite, element analysis, where developers are expected to deal with very large matrices but only a few non-zero coefficients, one may store the non-zero coefficients only, in order to reduce memory consumption and improve performance. Such matrix is called a Sparse matrix.

Here we mainly focus on the construction and usage of dense matrix. For details of sparse matrix, please visit https://eigen.tuxfamily.org/dox/group__TutorialSparse.html.

Matrix and Array

The APIs of Array class provide coefficient-wise operations, while the APIs of the Matrix class provide linear algebra operations.

Template parameters

The templates of Matrix and Array are shown below.

1
2
3
4
5
6
7
8
9
Matrix<typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime,
int Options = 0,
int MaxRowsAtCompileTime = RowsAtCompileTime,
int MaxColsAtCompileTime = ColsAtCompileTime>

// The parameters of Array is as same as above.
Array<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>

  • Scalar is the scalar type. Eigen currently supports all standard floating-point types (float, double, complex<float>, complex<double>, long double), as well as all native integer types (int, unsigned int, short, etc.), and bool.
  • RowsAtCompileTime and ColsAtCompileTime are the number of rows and columns at compile time. When developer cannot tell to the compiler the exact dimensions of the matrix, he could fill with the special value Dynamic, and indicates the size in constructor.
  • Options is a bit field to indicate the storage order; By default, it is ColMajor.
  • MaxRowsAtCompileTime and MaxColsAtCompileTime may be useful if a small dynamic-size matrix is required. After specifing these two params, compiler will allocate a memory on stack according to the upper bound, then avoid dynamic memory allocation.

Storage Order

  • RowMajor and ColMajor matrices can be mixed in expressions.
  • Other libraries may require a certain storage order. In such cases, user could construct the objects with the expcted order in the whole program.
  • Algorithms traversing a matrix row by row will go faster in a row-major matrix because of better data locality; Column-by-column traversal, similarly.
  • The default in Eigen is ColMajor. Naturally, Eigen work best with column-major matrices.

Fixed-size and Dynamic-size

  1. A fixed-size matrix is just a plain array, which is treated as a local variable and allocated on the stack; So a large fixed-size matrix may cause a stack overflow. For matrices with small sizes (typically smaller than \(4 \times 4\), up to \(16 \times 16\)), fixed-size usually performs better, as there's no run-time cost, and it is easy to be optimized with loop unwinding.
  2. Dynamic-size matrices are allocated on heap; Their number of rows and columns are stored as member variables. Eigen will be more aggressive trying to vectorize (use SIMD instructions) when operating dynamic-size matrices.
  3. Fixed-size matrices allow compiler to do more rigorous checking towards the validity of the operation, at the costs of longer compilation time and larger executable.

Loop unrolling, also known as loop unwinding, is a loop transformation technique that attempts to optimize a program's execution speed at the expense of its binary size, which is an approach known as space–time tradeoff.

For example, suppose a normal loop:

1
2
3
4
5
int x; 
for (x = 0; x < 100; x++)
{
delete(x);
}
After loop unrolling:
1
2
3
4
5
6
7
8
9
int x; 
for (x = 0; x < 100; x += 5 )
{
delete(x);
delete(x + 1);
delete(x + 2);
delete(x + 3);
delete(x + 4);
}

Convenience typedefs

Eigen defines the following Matrix typedefs:

  • MatrixNt for Matrix<t, N, N>.
  • VectorNt for Matrix<t, N, 1>.
  • RowVectorNt for Matrix<t, 1, N>.

Where N can be any one of 2, 3, 4, or X (for Dynamic); t can be any one of i (int), f (float), d (double), cf (complex), or cd (complex).

For example:

  • MatrixXd means typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
  • Vector3f means typedef Matrix<float, 3, 1> Vector3f;

Some commonly used predefined type of Array includes

Type Typedef
Array<float,Dynamic,1> ArrayXf
Array<float,3,1> Array3f
Array<double,Dynamic,Dynamic> ArrayXXd
Array<double,3,3> Array33d
Array<int,1,Dynamic> RowArrayXi

Constructor

Default constructor

1
2
Matrix3f a;
MatrixXf b;

Fixed-size matrix a is a 3-by-3 matrix, with a plain float[9] array of uninitialized coefficients; Dynamic-size matrix b is a null matrix with no memory allocated.

Constructor with sizes

1
2
MatrixXf a(10,15);
VectorXf b(30);

For matrices, pass the number of rows first then number of columns; For vectors, pass the length only. They will allocate the memory with the given size and leave the coefficients uninitialized.

In order to offer a uniform API across fixed-size and dynamic-size matrices, it is allowed to pass the sizes to the constructor for fixed-size matrix.

Matrix3f a(3,3); is a legal no-operation.

Constructor with coefficients

Vector2d, Vector3d, and Vector4d, it is allowed to pass the coefficients directly.

1
2
3
Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);

Initializer

Comma initializer

Eigen offers a comma initializer which allows users to pass values using <<; Values are seperated by ,. The size of the matrix needs to be defined beforehand; Otherwise, compiler will complain if the size of matrix mismatchs the number of coefficients.

Comma with numeric values

1
2
Matrix3f m;
m << 1, 2, 3, 4, 5, 6, 7, 8, 9;

\[m = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\]

Comma with vectors or matrices.

This will join vectors or matrices together.

1
2
3
4
5
6
RowVectorXd vec1(3);
vec1 << 1, 2, 3;
RowVectorXd vec2(4);
vec2 << 1, 4, 9, 16;
RowVectorXd joined(7);
joined << vec1, vec2;

\[joined = \begin{bmatrix} 1 & 2 & 3 & 1 & 4 & 9 & 16 \end{bmatrix}\]

1
2
3
4
5
MatrixXf matA(2, 2);
matA << 1, 2, 3, 4;
MatrixXf matB(4, 4);
matB << matA, matA/10, matA/10, matA;
std::cout << matB << std::endl;

\[matB = \begin{bmatrix} 1 & 2 & 0.1 & 0.2 \\ 3 & 4 & 0.3 & 0.4 \\ 0.1 & 0.2 & 1 & 2 \\ 0.3 & 0.4 & 3 & 4 \end{bmatrix}\]

Temporary Objects

Comma initializer can be used to construct temporary objects. finished() after initialization is required to indicate the accomplishment of it.

1
2
MatrixXf mat = MatrixXf::Random(2, 3);
mat = (MatrixXf(2,2) << 0, 1, 1, 0).finished() * mat;

Pre-defined matrices and arrays

The Matrix and Array classes have static methods like Zero(), Random(), Constant() etc. for initializing special matrices accordingly. Depending on the size at compile time, the syntax of initialization varies. Suppose XX is a data type and xx is an object. Func will return an object and setFunc() will modify the values in place.

  • For fixed-size objects, XX::Func([values]), xx::setFunc([values])
  • For 1D dynamic-size objects, XX::Func(length, [values]), xx::setFunc(length, [values])
  • For 2D dynamic-size objects, XX::Func(rows, cols, [values]), xx::setFunc(rows, cols, [values])

Func could be

  • Zero()
  • Ones()
  • Constant(value)
  • Random() \\ within range [-1, 1]
  • LinSpaced(size, low, high) \\only available for 1D objects
  • Identity() \\only available for 2D objects

Basis Vectors

It return an expression of the i-th unit (basis) vector.

Fixed-Size Vectors Dynamic-Size Vectors
XX::UnitX() \(=>\begin{bmatrix} 1 & \{,0\}^* \end{bmatrix}\)
XX::UnitY() \(=>\begin{bmatrix} 0 & 1 & \{,0\}^* \end{bmatrix}\)
XX::UnitZ() \(=>\begin{bmatrix} 0 & 0 & 1 & \{,0\}^* \end{bmatrix}\)
XX::Unit(size, i)
e.g. VectorXf::Unit(4,1) \(=>\begin{bmatrix} 0 & 1 & 0 & 0 \end{bmatrix}\)

Accessor

Those accessors could be used as both lvalues and rvalues. As usual with other expressions, it has no runtime cost before evaluation. More detailed information are demostrated in

Coefficient Accessor

Both operator () and[] is overloaded for accessing the coefficients; Same as normal array index in C++, it is zero-based. For vectors, both () and [] is valid; For matrices, since m[i, j] will be treated as m[j], only () is valid.

1
2
3
4
5
MatrixXf a(2, 2);
a(0, 1) = 3.0;
VectorXd v(2);
v(1) = 5.0;
v[0] = 2.0;

Block

A block is a rectangular part of matrix or array. It could be selected along a corner or a boundary. For each type of selection, only one example is listed for simplicity's sake.

Operation Dynamic-size Fixed-size
Block of size (p,q) starting at (i,j) m.block(i,j,p,q) m.block<p,q>(i,j)
Corner: Top-Left m.topLeftCorner(p,q) m.topLeftCorner<p,q>()
Half: Upper q Rows m.topRows(q) m.topRows<q>()
Half: Left p Columns m.leftCols(p) m.leftCols<p>()

Rows and Columns

Individual columns or rows could be selected by

1
2
m.col(idx); // the idx-th column
m.row(idx); // the idx-th row

Sub-vectors

Operation Dynamic-size Fixed-size
First n elements of vector v.head(n) v.head<n>()
Last n elements of vector v.tail(n) v.tail<n>()
n elements starting at i vector.segment(i, n) vector.segment<n>(i)

Diagonals

  • m.diagonal([idx])

Slicing and Map

Map

It can be used to process non-eigen data without any overhead.

1
2
3
Map< typename PlainObjectType, 
int MapOptions,
typename StrideType >
  • PlainObjectType: the type after mapping
  • MapOptions: specifies the pointer alignment in bytes. It can be: Aligned128, Aligned64, Aligned32, Aligned16, Aligned8 or Unaligned. By default is Unaligned.
  • StrideType: optional. By default, Map assumes the memory layout of an ordinary, contiguous array. This can be overridden by specifying strides. The type passed here must be a specialization of the Stride template.

Stride

1
2
3
4
Stride< int _OuterStrideAtCompileTime, 
int _InnerStrideAtCompileTime>
InnerStride<_InnerStrideAtCompileTime = Dynamic>
OuterStride<_OuterStrideAtCompileTime = Dynamic>
  • InnerStride is the pointer increment between two consecutive entries within a given row of a row-major matrix or within a given column of a column-major matrix.
  • OuterStride is the pointer increment between two consecutive rows of a row-major matrix or between two consecutive columns of a column-major matrix.
1
2
3
4
int array[24]; for(int i = 0; i < 24; ++i) array[i] = i;
cout << Map<MatrixXi, 0, Stride<Dynamic,2> >
(array, 3, 3, Stride<Dynamic,2>(8, 2))
<< endl;

The output will be

1
2
3
0  8 16
2 10 18
4 12 20

Slicing

  • For fixed-size matrix: Map(dataPtr, stride)
  • For dynamic-size vector: Map(dataPtr, size, stride)
  • For dynamic-size matrix: Map(dataPtr, rows, cols, stride)

Operation

Arithmetic

Eigen doesn't provide implicit type promotion; Therefore, the scalar type of left-hand side and right-hand side must match.

Addition and Subtraction

Array-Array and Matrix-Matrix

  • binary operator: + as in a + b; - as in a - b
  • unary operator: - as in - a
  • compound operator: += as in a += b; -= as in a -= b

Array-Scalar

The operators are same as above.

A 'matrix-scalar' addition and subtraction is not supported; You are expected to explicitly convert the data type into array first.

Multiplication and Division

Matrix-Scalar and Array-Scalar Multiplication and Division

  • binary operator: * as in matrix * scalar or scalar * matrix; / as in matrix / scalar
  • compound operator: *= as in matrix *= scalar; /= as in matrix /= scalar

Matrix-Matrix

  • binary operator: * as in a*b
  • compound operator *= as in a*=b (which is equivalent to a = a*b)

Coefficient-wise Multiplication and Division

  • Array class naturally provides coefficient-wise product and divition with operator * and /.
  • Matrix have .cwiseProduct(.) only.

Coefficient-wise Operations

Array-Array and Array-Scalar Comparison

  • <, <=, >, >=
  • .min(.), .max(.)

Matrix-Matrix and Matrix-Scalar Comparison

  • .cwiseMin(.), .cwiseMax(.)
  • .cwiseEqual(.), .cwiseNotEqual(.)

.min(.) and .max(.) construct an array whose coefficients are the minimum/maximum of the given two arrays.

Other STL-like operatons

Below could be applied to both Matrix and Array

Array Matrix Array Matrix
a.abs(), abs(a) m.cwiseAbs() a.abs2(), abs2(a) m.cwiseAbs2()
a.inverse(), inverse(a) m.cwiseInverse() a.conjugate(), conj(a) m.conjugate()
a.real(), real(a) real(m) a.imag(), imag(a) imag(m)
a.sqrt(), sqrt(a) m.cwiseSqrt()

Below are Array only

Array Array Array Array
a.exp(), exp(a) a.log(), log(a) a.log1p(), log1p(a) a.log10(), log10(a)
a.pow(e), pow(a,e) a.rsqrt(), rsqrt(a) a.square(), square(a) a.cube(), cube(a)
a.sin(), sin(a) a.cos(), cos(a) a.tan(), tan(a) a.asin(), asin(a)
a.acos(), acos(a) a.atan(), atan(a) a.sinh(), sinh(a) a.cosh(), cosh(a)
a.tanh(), tanh(a) a.ceil(), ceil(a) a.floor(), floor(a) a.round(), round(a)
a.isFinite(), isfinite(a) a.isInf(), isinf(a) a.isNaN(), isnan(a)

Linear Algebra

Dot and Cross Product

1
2
3
Vector3f m, n;
m.dot(n); // dot product of m and n
m.cross(n); //cross product of m and n

Cross product is only for vectors of size 3.

Transpose, Conjugate, and Adjoint

Normal Modifying In-place
Transpose $ a^T $ .transpose() .transposeInPlace()
Conjugate $ {a} $ .conjugate() .conjugateInPlace()
Adjoint $ a^* $ .adjoint() .adjointInPlace()
Reverse $ a^{-1} $ .reverse() .reverseInPlace()

Norm and Trace

  • .squaredNorm() and .norm()
    • For vectors, \(\ell^{2}\) norm.
    • For matrices, "Frobenius" or "Hilbert-Schmidt" norm.
  • .lpNorm<p>()
    • p could be integers or Infinity for computing \(l^{\infty}\) norm.
  • .trace()

Decompositions and Problem Solving

Please visit http://eigen.tuxfamily.org/dox/group__DenseLinearSolvers__chapter.html

Reduction

Reduction operations are operations that reduce a matrix or vector into a single value.

Given an array or matrix, below will return single values.

1
2
3
4
5
6
Matrix3f m;
m.sum(); // sum of coefficients
m.mean(); // mean of coefficients
m.prod(); // product of coefficients
m.maxCoeff(); // max coefficient
m.minCoeff(); // min coefficient

Furthermore, for minCoeff and maxCoeff, the index of the value is also accessible by passing the address.

1
2
3
Matrix3f m = Matrix3f::Random();
std::ptrdiff_t i, j;
float minOfM = m.minCoeff(&i,&j);

Boolean Reductions

  • .all() returns true if all of the coefficients are evaluated to true .
  • .any() returns true if at least one of the coefficients are evaluated to true.
  • .count() returns the number of coefficients are evaluated to true.

Broadcasting and Partial Reduction

Partial Reduction

Partial reductions apply the reduction operations on each column or row, and return a column or row vector with the corresponding values.

For example,

1
2
3
4
5
Eigen::MatrixXf mat(2,4);
mat << 1, 2, 6, 9,
3, 1, 7, 2;
std::cout << mat.colwise().maxCoeff() << std::endl; //output will be [3 2 7 9]
std::cout << mat.rowwise().maxCoeff() << std::endl; // output will be [9 // 7]

Broadcasting

Broadcasting could be applied to Matrix-Vector and Array-ArrayXN (equivalent for vector under Array context) expression that interprets the Vector as a matrix via replicating.

1
2
3
4
5
mat << 1, 2, 6, 9,
3, 1, 7, 2;
v << 0,
1;
mat.colwise() += v;

This expression means

\[\begin{bmatrix} 1 & 2 & 6 & 9 \\ 3 & 1 & 7 & 2 \end{bmatrix} + \begin{bmatrix} 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 \end{bmatrix} = \begin{bmatrix} 1 & 2 & 6 & 9 \\ 4 & 2 & 8 & 3\end{bmatrix}\]

The vector operand must be of type Vector or ArrayXN; Otherwise, a compile-time error will be raised.

Replication

Replicate< MatrixType, RowFactor, ColFactor > describes the multiple replication of a matrix or vector.

  • MatrixType, the type of the object we are replicating
  • RowFactor, number of repetitions at compile time along the vertical direction, can be Dynamic.
  • ColFactor, number of repetitions at compile time along the horizontal direction, can be Dynamic.
1
2
3
4
MatrixXi m(2, 3);
m << 7, 6, 9,
-2, 6, -6;
cout << m.replicate<3,2>() << endl;

m.replicate<3,2>() or m.replicate(3, 2) will be

\[\begin{bmatrix} 7 & 6 & 9 & 7 & 6 & 9 \\ -2 & 6 & -6 & -2 & 6 & -6 \\ 7 & 6 & 9 & 7 & 6 & 9 \\ -2 & 6 & -6 & -2 & 6 & -6 \\ 7 & 6 & 9 & 7 & 6 & 9 \\ -2 & 6 & -6 & -2 & 6 & -6 \end{bmatrix}\]

This can also combine with broadcasting.

1
2
Vector3i v(7, 2, 6);
cout << v.rowwise().replicate(5) << endl;

The output will be \[\begin{bmatrix} 7 & 7 & 7 & 7 & 7 \\ -2 & -2 & -2 & -2 & -2 \\ 6 & 6 & 6 & 6 & 6 \end{bmatrix}\]

Array-Matrix Conversion

Mixing matrices and arrays in an expression is forbidden with Eigen; Therefore, eigen provides explict type conversion approaches .matrix() and .array(); Both .matrix() and .array() can be used as rvalues or lvalues.

An exception is that it is valid to assign a matrix expression to an array variable, or to assign an array expression to a matrix variable.

Resize

Trying to resize a fixed-size matrix will trigger an assertion failure.

Get the Shape info

The shape of a matrix can be retrieved via rows(), cols() and size(). These methods return the number of rows, the number of columns and the number of coefficients, respectively.

Reshape by API

resize(nRows, nCols) could change the shape of a dynamic matrix. If the size become consistent, resize is a no-operation; Otherwise, the values of the coefficients may change. If you want to keep the values invariant, use conservativeResize() instead.

Reshape by assignment

Assignment is the action of copying a matrix into another, using operator =. If the left-hand size is a dynamic matrix, Eigen may resize it implicitly in order to match the size of the matrix on the right-hand side.

1
2
3
MatrixXf a(2,2);
MatrixXf b(3,3);
a = b; //it is valid and then a become a 3 x 3 matrix

Expression Object and Aliasing

Expression Object

In Eigen, arithmetic operators such as operator + don't perform computation by themselves, they just return an "expression object" describing the computation to be performed. The actual computation happens later, when the whole expression is required to be evaluated, typically in operator =. Then optimizing compiler will output a perfectly optimized code. Thus, you should not be afraid of using relatively large arithmetic expressions with Eigen.

For example,

1
2
VectorXf a(50), b(50), c(50), d(50);
a = 3*b + 4*c + 5*d;

Eigen will do one loop only, which will look like this:

1
2
for(int i = 0; i < 50; ++i)
a[i] = 3*b[i] + 4*c[i] + 5*d[i];

Alias

In Eigen, aliasing refers to assignment statements that the same matrix/array/vector appears on both left and right size of the assignment operator =. .eval() may be required to avoid aliasing by evaluating the right-hand side fully into a temporary matrix/array/vector and then assign it to the left-hand side.

1
2
Matrix2i a; a << 1, 2, 3, 4;
a = a.transpose(); // !!! do NOT do this !!!

Then a will become

1
2
1 2
3 4

Aliasing cannot be detected at compile time. Most operations in Eigen assume that there are no aliasing problem, except for Squared Matrix multiplication; By default, if matA is a squared matrix, matA * matA will be interpreted as

1
2
tmp = matA*matA;
matA = tmp;

If you're sure that matrix product can be safely evaluated into the destination matrix without aliasing issue, then you can use the .noalias() function to avoid the temporary, like matB.noalias() = matA * matA. This allows Eigen to evaluate the matrix product matA * matA directly into matB.

Geometric Module

Geometry module provides two different kinds of geometric transformations:

  • Abstract transformations, which are not represented as matrices, such as rotation, translation, scaling. But it's valid to operate with matrix/vectors or convert them into matrices.
  • Transform, Projective or affine transformation matrices
  • It's allowed to construct Transform from abstract transformations, for example, Transform t (AngleAxis(angle,axis))

Accessor

  • Transform matrix t.matrix() => \((N + 1) \times (N + 1)\) matrix
  • Coefficients t(i,j), t.matrix()(i,j) => scalar type
  • Translation part t.translation() => \(N \times 1\) vector
  • Linear part t.linear() => \(N \times N\) matrix
  • Rotation t.rotation() => \(N \times N\) matrix

Compatibility with OpenGL

  • For manipulating OpenGL 4x4 matrices then Affine3X are what you want.
  • Transform::data() method could pass the transformation matrix to OpenGL.

Conversion

Any transformations can be converted to any other types of the same nature, or to a more generic type. For example:

1
2
3
AngleAxisf aa;  aa = Quaternionf(..);
AngleAxisf aa; aa = Matrix3f(..);
Affine3f m; m = Translation3f(..);

Operations

2D rotation with angle Rotation2D<float> rot2(angle)
3D rotation with angle and normalized axis AngleAxis<float> aa(angle, axis)
3D rotation with quaternion Quaternion<float> q;
q = AngleAxis<float>(angle, axis)
Scaling Scaling(sx, sy)
Scaling(sx, sy, sz)
Scaling(s)
Scaling(vecN)
Translation Translation<float,2>(tx, ty)
Translation<float,3>(tx, ty, tz)
Translation<float,N>(s)
Translation<float,N>(vecN)
Affine transformation Transform<float,N,Affine> t = composition_of_others
Slerp rot1.slerp(alpha,rot2)
Normalize vector.normalized()
Hnormalize hnormalized(), divided by the last coefficient first then normalize it
Homogeneous v.homogeneous(), add 1 at the end

To transform a set of vectors, use rotation matrix; Otherwise, usa Quaternion as it is compact, fast and stable.

For further details please visit http://eigen.tuxfamily.org/dox/group__Geometry__Module.html

Composition

Type Before After
Translation t.translate(vector) t.pretranslate(vector)
Rotation t.rotate(rotation) t.prerotate(rotation)
Scaling t.scale(vector), t.scale(s) t.prescale(vector), t.prescale(s)
2D Shear t.shear(sx,sy) t.preshear(sx,sy)