Simple Vector Library (1.5) |

Contents |

- Description
- Classes
- Element Access
- Arithmetic Operators and Functions
- Constants
- Constructors
- Input and Output
- Transformations
- Compiling with SVL
- Using SVL With OpenGL
- Author

Description |

The Simple Vector Library (SVL) provides vector and matrix classes, as well as a number of functions for performing vector arithmetic with them. Equation-like syntax is supported via class operators, for example:

#include "svl/SVL.h"Both generic (arbitrarily-sized), and fixed-size (2, 3 and 4 element) vectors and matrices are supported. The latter are provided for the efficient manipulation of vectors or points in 2D or 3D space, and make heavy use of inlining for frequently-used operations. (One of the design goals of SVL was to ensure that it was as fast as the C-language, macro-based libraries it was written to replace.)

Vec3 v(1.0, 2.0, 3.0);

Mat3 m(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);

v = 2 * v + m * v;

v *= (m / 3.0) * norm(v);

cout << v << endl;

SVL is a subset of VL, a more extensive vector library, which in addition contains classes for sparse vector/matrices, sub-vector/matrices, and implementations of some iterative solvers. Whereas with SVL the component type of vectors and matrices is defined with a compile-time switch, with VL you specify the type explicitly (Vec2f, Vec2d) and can, for example, mix matrices of doubles with vectors of floats.

SVL requires C++. It is known to compile under Irix CC, g++, and MSVC.
The latest version can be retrieved from http://www.cs.cmu.edu/~ajw/public/dist/.
This documentation can be found online at http://www.cs.cmu.edu/~ajw/doc/svl.html.

Classes |

SVL contains the following types and classes:

Fixed-size:

Real component type (float or double)

Vec2 2-vector

Vec3 3-vector

Vec4 4-vector

Mat2 2 x 2 matrix

Mat3 3 x 3 matrix

Mat4 4 x 4 matrix

Generic:

Vec n-vector

Mat n x m matrix

Element Access |

The elements of a vector or matrix are accessed with standard C array notation:

For the resizeable vector types, the current size can be obtained from the

v[2] = 4.0; // set element 2 of the vector

m[3][4] = 5.0 // set row 3, column 4 of the matrix

m[2] = v; // set row 2 of the matrix

for (i = 0; i < v.Elts(); i++)

v[i] = i;

for (i = 0; i < m.Rows(); i++)Though it seems slightly unintuitive, if you have a pointer to a vector or matrix, you must dereference it first before indexing it:

for (j = 0; j < m.Cols(); j++)

m[i][j] = i + j;

(*vPtr)[20] = 3.0;If you need a pointer to the data belonging to a vector or matrix, use the Ref() method. (Matrices are stored by row.)

Real *vecDataPtr = v.Ref(), *matDataPtr = m.Ref();

**Note**: If you compile with the symbol
VL_DEBUG, index range checks will be performed on all element accesses.

Arithmetic Operators and Functions |

Basic arithmetic: + - * /Vector multiplication and division is pairwise: (a * b)[i] = a[i] * b[i]. (See below for how to form the dot product of two vectors with dot().) Matrix multiplication is defined as usual, and matrix division is undefined.

Accumulation arithmetic: += -= *= /=

Comparison: ==, !=

For both matrices and vectors, multiplication and division by a scalar is also allowed. Matrices can be multiplied either on the left or the right by a vector. In the expression m * v, v is treated as a column vector; in the expression v * m, it is treated as a row vector.

In the above, VecN is either a Vec or a Vec[234], and Real is a Float or a Double, depending on the argument type. For more on the use of the

Real dot(const VecN &a, const VecN &b); // inner product of a and b

Real len(const VecN &v); // length of v: || v ||

Real sqrlen(const VecN &v); // length of v, squared

VecN norm(const VecN &v); // v / || v ||

Vec2 cross(const Vec2 &a); // vector orthogonal to a

Vec3 cross(const Vec3 &a, const Vec3 &b); // vector orthogonal to a and b

Vec4 cross(const Vec4 &a, const Vec4 &b, const Vec4 &c);

// vector orthogonal to a, b and c

Vec2 proj(const Vec3 &v); // homog. projection: v[0..1] / v[2]

Vec3 proj(const Vec4 &v); // homog. projection: v[0..2] / v[3]

MatN trans(const MatN &m); // Transpose of mIn the above, MatN is any matrix type, a, though the

Real trace(const MatN &m); // Trace of m

MatN adj(const MatN &m); // Adjoint of m

Real det(const MatN &m); // Determinant of m

MatN inv(const MatN &m); // Inverse of m, if it exists.

Constants |

There are a number of 'magic' constants in SVL that can be used to initialise vectors or matrices with simple assignment statements. For example:

Vec3 v; Mat3 m; Vec v8(8);Below is a summary of the constants defined by SVL.

v = vl_0 [0, 0, 0]

v = vl_y [0, 1, 0]

v = vl_1 [1, 1, 1]

m = vl_0; 3 x 3 matrix, all elts. set to zero.

m = vl_1; 3 x 3 identity matrix

m = vl_B; 3 x 3 matrix, all elts. set to one.

v8 = vl_axis(6); [0, 0, 0, 0, 0, 0, 1, 0]

vl_one/vl_1/vl_I vector of all 1s, or identity matrix

vl_zero/vl_0/vl_Z vector or matrix of all 0s

vl_B matrix of all 1s

vl_x, vl_y, vl_z, vl_w x, y, z and w axis vectors

vl_axis(n) zero vector with element n set to 1

vl_pi pi!

vl_halfPi pi/2

Constructors |

In general, a vector or matrix constructor should be given either one of the initialiser constants listed above, or a list of values for its elements. If neither of these is supplied, the variable will be uninitialised. The first arguments to the constructor of a generic vector or matrix should always be the required size. Thus matrices and vectors are declared as follows:

Vec[234] v([initialisation_constant | element_list]);If generic vectors or matrices are not given a size when first created, they are regarded as empty, with no associated storage. This state persists until they are assigned a matrix/vector or the result of some computation, at which point they take on the dimensions of that result.

Vec v([elements, [initialisation_constant | element_list]]);

Mat[234] m([initialisation_constant | element_list]);

Mat m([rows, columns, [initialisation_constant | element_list]]);

Examples:

Vec3 v(vl_1);

Vec3 v(1.0, 2.0, 3.0);

Vec v(6, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);

Vec v(20, vl_axis(10));

Mat2 m(1.0, 2.0, 3.0, 4.0);

Mat m(10, 20, vl_I);

Finally, to set the size of a empty matrix or vector explicitly, or resize an existing matrix or vector, use the SetSize method:

v.SetSize(23);

m.SetSize(10, 20);

Input
and Output |

All of the vector and matrix types in SVL can be used in iostream-type expressions. For example:

#include <iostream.h>will output

Vec3 v(vl_1);

cout << v << 2 * v << endl;

cin >> v;

[1 1 1][2 2 2]and then prompt for input. Vectors and matrices are parsed in the same format that they are output: vectors are delimited by square brackets, elements separated by white space, and matrices consist of a series of row vectors, again delimited by square brackets.

Transformations |

The following are the transformations supported by SVL.

Mat2 Rot2(Real theta)Transformations with a prefix of 'H' operate in the homogeneous coordinate system, which allows translation and shear transformations, as well as the usual rotation and scale. In this coordinate system an n-vector is embedded in a (n+1)-dimensional space, e.g., a homogeneous point in 2d is represented by a 3-vector.

// rotate a 2d vector CCW by theta

Mat2 Scale2(const Vec2 &s)

// scale by s around the origin

Mat3 HRot3(Real theta)

// rotate a homogeneous 2d vector CCW by theta

Mat3 HScale3(const Vec2 &s)

// scale by s around the origin, in homogeneous 2d coords.

Mat3 HTrans3(const Vec2 &t)

// translate a homogeneous 2d vector by t

Mat3 Rot3(const Vec3 &axis, Real theta)

// rotate a 3d vector CCW around axis by theta

Mat3 Rot3(const Vec4 &q)

// rotate a 3d vector by the quaternion q

Mat3 Scale3(const Vec3 &s)

// scale by s around the origin

Mat4 HRot4(const Vec3 &axis, Real theta)

// rotate a homogeneous 3d vector CCW around axis by theta

Mat4 HRot4(const Vec4 &q)

// rotate a homogeneous 3d vector by the quaternion q

Mat4 HScale4(const Vec3 &s)

// scale by s around the origin, in homogeneous 3d coords

Mat4 HTrans4(const Vec3 &t)

// translate a homogeneous 3d vector by t

To convert from non-homogeneous to homogeneous vectors, make the extra coordinate (usually 1) the second argument in a constructor of/cast to the next-higher dimension vector. To project from a homogeneous vector down to a non-homogeneous one (doing a homogeneous divide in the process), use the proj() function. This process can be simplified by the use of the xform() function, which applies a transform to a vector, doing homogeneous/nonhomogeneous conversions if necessary. For example:

Vec3 x,y;By default, SVL assumes that transformations should operate on column vectors (v = T * v), though it can be compiled to assume row vectors instead (v = v * T).

// apply homogeneous transformations to a 3-vector

x = proj(Scale4(...) * Rot4(...) * Trans4(...) * Vec4(y, 1.0));

// do the same thing with xform()

x = xform(Scale4(...) * Rot4(...) * Trans4(...), y);

Compiling with SVL |

VL_FLOAT - use floats instead of doubles

VL_DEBUG - turn on index checking and assertions

VL_ROW_ORIENT - transformations operate on row vectors instead of column vectors

Using
SVL With OpenGL |

SVL comes with a header file, SVLgl.h, which makes using SVL vectors with OpenGL more convenient. For example:

#include "svl/SVLgl.h"

Vec3 x(24, 0, 100), y(40, 20, 10);

glBegin(GL_LINES);

glVertex(x);

glVertex(y);

glEnd();

Author |

Please forward bug reports, comments, or suggestions to:

Andrew Willmott (ajw+svl@cs.cmu.edu), Graphics Group, SCS, CMU.