Just like vectors, points defined in nalgebra are elements of However, they both have different uses, depending on your application.
- In a very general context: vectors are what you choose when you need a bag of coordinates (relative to a suitable basis). Points will not be useful for you as they support much less operations than vectors. Vectors support most common operations like cross product, dot product, componentwise binary operations, etc. Simply search for the name of the operation you want on the root module documentation and it will likely be listed as a free function or a method. If you can't find what you need, feel free to open an issue or ask about it on the user forum.
- In a geometric context: a point is an element of an euclidean space, while a vector is an element of the underlying vector space. In other words, a point is a location in space while a vector is a translation, i.e., the displacement required to move from one point to another:
Intuition can often be safely used to anticipate which operations are or are not allowed between points, and what is the relation between a vector and a point. In particular:
- A point's coordinates vector can be accessed as a public field:
- The sum of a point with a vector returns another point which is the translation of by the vector .
- The difference of two point and returns the vector such that .
- The sum, multiplication and division of two points are meaningless and not supported by nalgebra.
- For convenience, you may compute the center of two points using the
- The homogeneous
coordinates of a point
usually end with a
1while those of a vector always ends with a
- Points are affected by the translational component of transformations while vectors are only rotated and scaled:
Points can be created with various constructors:
|Builds the point with all its coordinates set to zero.|
|Builds the point with coordinates vector equal to |
|Builds a point with the given homogeneous coordinates, i.e., with all its components divided by the last one (which is then removed).|
|Builds the point with the given coordinates. Works only for points with a dimension known at compile-time and smaller than 6.|
|Builds the point with all its coordinates set to the maximal value of the underlying scalar type.|
|Builds the point with all its coordinates set to the minimal value of the underlying scalar type.|
Transformations are algebraic entities that act on points and vectors to change
their coordinates. The following figure shows the whole spectrum of
transformations supported by dedicated types on nalgebra (notations like
Affine2/3 means either
All the types shown in this diagram are actually type aliases for types generic
wrt. the dimension and with a name ending with
Base instead of a number,
i.e., the base implementation of the translation is
TranslationBase. The more
aliases for the parametrized type
TransformBase<..., Category> where its last
Category specifies which of the three variants is represented.
Note that raw matrices can also be interpreted as general transformations that
are not necessarily invertible. This may be useful in a generic
Transformations can be composed (by multiplication) even if they do not have
the same type. The type of the composition result is the most general
transformation of both. For example, multiplying a
transformation) with a
Similarity3 yields a
Projective3 because all
similarities are inversible. An exception is the product of any pure rotation
by a pure translation: none is more general than the other so the result is an
Isometry2/3 which is the most specific transformation enough to represent
Converting a transformation to one that is more general is possible with the
na::convert(...) function. The other way round is sometimes possible using
na::try_convert(...) which returns a non-
None value in case of success. For
example, converting a
Similarity2 to an
Isometry2 will succeed only if the
similarity scaling factor is one (which is checked at run-time by
::try_convert(...)). Note that if you do not want to consume your input
value upon conversion, use
na::try_convert_ref(...) with references instead.
Forcing the conversion of a transformation to a more specific one is possible
is typically used when you know that the conversion is valid and want to avoid
the run-time algebraic properties tests performed by
is unsafe but guaranteed to work properly if the following conditions are met:
- Both objects use the same storage buffer type. If they don't, using the result is Undefined Behavior.
- You know the value being converted fulfills the invariants of the target type. If they don't, the returned value might violate those invariants and cause future uses of the result to yield unexpected results.
In any cases, both objects may safely use different compatible scalar types (where compatible means that they are both integer types, or both floating point types, etc.)
A rotation is an invertible origin-, distance- and orientation-preserving transformation. It is commonly known by algebraists as the -dimensional Special Orthogonal group :
2D (resp. 3D) rotations are available as the
UnitQuaternion) structures. Unit quaternions and
rotation matrices have three construction methods in common:
|Builds a rotation of |
|This is the same as |
|Builds a rotation from its roll, pitch, and yaw components applied in that order.|
::from_matrix_unchecked(...) will initialize a rotation matrix
from a raw
Matrix3. In that case, it is not checked whether or
not it is actually a rotation. This should be used with great care.
Finally, an unit complex or an unit quaternion may be constructed from, or
converted to, a
Direct isometries are rotations followed by translations, i.e., they preserve orientations and distances, but not the origin. They are commonly known by algebraists as the -dimensional Special Euclidean group . Note that isometries that are not direct because they include a reflexion are not yet supported by nalgebra.
2D and 3D isometries are available as the
structures. They are internally represented as a translation vector and an unit
complex number (for 2D) or an unit quaternion (for 3D). For isometries
containing rotation matrices instead, use
|Builds an isometry that rotates by |
|The isometry with does nothing, i.e., a zero translation and a identity rotation.|
|Builds an isometry from a translation |
|Same as |
Direct isometries are commonly used to represent the position and orientation of a solid object or a camera. Convenient constructors are thus provided to center and orient an isometry as if it was the head of an observer:
|A right-handed look-at view matrix that makes the axis point toward the staring direction. This builds a transformation that maps a point from global coordinates into the local coordinates of a camera centered at point and looking at a second one.|
|A left-handed look-at view matrix. This is the same as |
|Builds a transformation that maps a point from the local coordinates of an observer into global coordinates. This is the inverse transformation of |
While the right-handed look-at and the observer-frame isometries are closely related (they are inverses of each other), they have very different semantic meanings. The former will typically be used in the context of rendering a scene. Indeed, we want to bring the objects into the local space of the camera for rendering. The latter will typically be used to orient a solid, a robot, a head, etc. because, in that case, we want to be able to localize our object into the global scene.
A similarity is an uniform scaling, followed by a rotation, followed by translation. Thus, it preserves angle sizes and maps parallel lines to parallel lines. Orientation is lost if the scaling factor is negative. They are usually known by algebraists as the -dimensional Similarity group .
Similarities share the same constructors as the isometry described in the previous section. Though most of them take one additional parameter: the uniform scaling factor.
We are used to work with cartesian coordinates. However, it has some limitations when it comes to represent transformations in matrix form. For example, the translational part of an isometry cannot be expressed in cartesian coordinates in a compact way (using a matrix). That's why homogeneous coordinates exist: rotations, scaling, and translations can all be combined in a single matrix of higher dimension than the euclidean space we are working with.
Any affine transformation have equivalent representations as raw matrices. In
particular, any 2D affine transformation is representable as a
any 3D affine transformation is representable as a
Matrix4. Each such raw
matrix is known as the homogeneous coordinates of the corresponding
transformation. The following example shows the homogeneous coordinate matrix
of a 2D similarity. Note that this process implicitly computes the rotation
matrix representation (which components are numbered from to ) of the unit
complex number that represents the rotational part of the underlying isometry:
Note that if is an homogeneous coordinate matrix of some transformation and
any real number, and are considered
equivalent. Therefore, any transformation has an infinite number of homogeneous
coordinates (just multiply every single entry of the raw matrix by a non-zero
real number). However, we usually only care about the representation with a 1
on the bottom-right entry as it simplifies computations. Use the
.to_homogeneous() method to compute the homogeneous coordinates of any
vector, point, or transformation.
It is natural to wonder how transformation expressed in homogeneous coordinates
can be applied to vectors and points. For example, multiplying a
Vector2 by a
Rotation2 will yield a rotated
Vector2. On the other hand, multiplying a
Vector2 by a
Matrix3, obtained by converting a 2D rotation to homogeneous
coordinates, will not even compile! The only solution is to somehow convert the
2D vector to a
Vector3 and perform the multiplication. The same reasoning
applies to points: we would need to convert the
Point2 to a
conversions can be made by computing the homogeneous coordinates of vectors and
points themselves with
Computing a vector's homogeneous coordinates will append a
0 to it while
computing a point's homogeneous coordinates will append a
This subtle difference reflects the fact emphasized at the beginning
of this chapter: transformations do not have the same effect on points as on
0 appended to vectors will cancel the translational component of
any transformation; the
1 appended to points will let it be translated
Points and vectors in homogeneous coordinates can be transformed back using
::from_homogeneous(...). For vectors, the last coordinate entry will be
removed. For points, the last coordinate will also be removed and every other
coordinate will be divided by it:
The following example shows the application of a transformation using two methods: with dedicated transformation types, and with homogeneous coordinates. While the end-results are the same, using dedicated types is much more concise and efficient.