12 KiB
Vector
Vector is a basic mathematical object that expresses direction and magnitude (such as velocity, force etc.) and is usually expressed as an "array of numbers". For example in two dimensional space an array [4,3]
expresses a vector pointing 4 units to the "right" (along X axis) and 3 units "up" (along Y axis) and has the magnitude 5 (which is the vector's length). Vectors are one of the very basic concepts of advanced math and are used almost in any advanced area of math, physics, programming etc. -- basically all of physics and engineering operates with vectors, programmers will mostly encounter them in areas such as 3D graphics, physics engines (forces, velocities, acceleration, ...), machine learning (feature vectors, ...) or signal processing (e.g. Fourier transform just interprets a signal as a vector and transforms it to a different basis) etc. In this article we will implicitly focus on vectors from programmer's point of view (i.e. "arrays of numbers"), which to a mathematician will seem very simplified, but we'll briefly also foreshadow the mathematical view.
Just like in elemental mathematics we deal with "simple" numbers such as 10, -2/3 or pi -- we retrospectively call such "simple" numbers scalars -- advanced mathematics generalizes the concept of such a number into vectors ("arrays of numbers", e.g. [1,0,-3/5]
or [0.5,0.5]
) and yet further to matrices ("two dimensional arrays of numbers") and defines a way to deal with such generalizations into linear algebra, i.e. we have ways to add and multiply vectors and matrices and solve equations with them, just like we did in elemental algebra (of course, linear algebra is a bit more complex as it mixes together scalars, vectors and matrices). In yet more advanced mathematics the concepts of vectors and matrices are further generalized to tensors which may also be seen as "N dimensional arrays of numbers" but further add new rules and interpretation of such "arrays" -- vectors can therefore be also seen as a tensor (of rank 1) -- note that in this context there is e.g. a fundamental distinction between row and column vectors. Keep in mind that vectors, matrices and tensors aren't the only possible generalization of numbers, another one is e.g. that of complex numbers, quaternions etc. Anyway, in this article we won't be discussing tensors or any of the more advanced concepts further, they are pretty non-trivial and mostly beyond the scope of mere programmer's needs :) We'll keep it at linear algebra level.
Vector is not merely a coordinate, though the traditional representation of it suggest such representation and programmers often use vector data types to store coordinates out of convenience (e.g. in 3D graphics engines vectors are used to specify coordinates of 3D objects); vector should properly be seen as a direction and magnitude which has no position, i.e. a way to correctly imagine a vector is something like an arrow -- for example if a vector represents velocity of an object, the direction (where the arrow points) says in which direction the object is moving and the magnitude (the arrow length) says how fast it is moving (its speed), but it doesn't say the position of the object (the arrow itself records no position, it just "hangs in thin air").
Watch out, mathematicians dislike defining vectors as arrays of numbers because vectors are essentially NOT arrays of numbers, such arrays are just one way to express them. Similarly we don't have to interpret any array of numbers as a vector, just as we don't have to interpret any string of letter as a word in human language. A vector is simply a direction and magnitude, an "arrow in space" of N dimensions; a natural way of expressing such arrow is through multiples of basis vectors (so called components), BUT the specific numbers (components) depend on the choice of basis vectors, i.e. the SAME vector may be written as an array of different numbers (components) in a different basis, just as the same concept of a dog is expressed by different words in different languages. Even with the same basis vectors the numbers (components) depend on the method of measurement -- instead of expressing the vector as a linear combination of the N basis vectors we may express it as N dot products with the basis vectors -- the numbers (components) will be different, but the expressed vector will be the same. Mathematicians usually define vectors abstractly simply as members of a vector space which is a set of elements (vectors) along with operations of addition and multiplication which satisfy certain given rules (axioms).
How Vectors Work
Here we'll explain the basics of vectors from programmer's point of view, i.e. the traditional "array of numbers" simplification (expressing a linear combination of basis vectors).
Given an N dimensional space, a vector to us will be an array of real numbers (in programming floats, fixed point or even just integers) of length N, i.e. the array will have N components (2 for 2D, 3 for 3D etc.).
For example suppose 2 vectors in a 2 dimensional space, u = [7,6] and v = [2,-3.5]. To visualize them we may simply plot them:
6 | _,
5 | __/| u
4 | __/
3 | __/
2 | __/
___1_|/._._._._._._._
-1 |\1 2 3 4 5 6 7
-2 | \
-3 | _\|
-4 | "" v
-5 |
NOTE: while for normal (scalar) variables we use letters such as x, y and z, for vector variables we usually use letters u, v and w and also put a small arrow above them as:
-> ->
u = [7,6], v = [2,-3.5]
The vector's components are referred to by the vector's symbol and subscript or, in programming, with a dot or square brackets (like with array indexing), i.e. u.x = 7, u.y = 6, v.x = 2 and v.y = -3.5. In programming data types for vectors are usually called vecN
or vN
where N is the number of dimensions (i.e. vec2
, vec3
etc.).
Also note that we'll be writing vectors "horizontally" just as shown, which means we're using so called row vectors; you may also see usage of so called columns vectors as:
-> |7| -> | 2 |
u = |6|, v = |-3.5|
Now notice that we do NOT plot the vectors as points, but as arrows starting at the origin (point [0,0]) -- this is again because we don't normally interpret vectors as a position but rather as a direction with magnitude. The direction is apparent from the picture (u points kind of top-right and v bottom-right) and can be exactly computed with arcus tangent (i.e. angle of u = atan(6/7) = 40.6 degrees, ...), while the magnitude (also length or norm) is given by the vector's Euclidean length and is denoted by the vector's symbol in ||
brackets (in programming the function for getting the length may be called something like len
, size
or abs
, even though absolute value is not really a mathematically correct term here), i.e.:
->
||u|| = sqrt(7^2 + 6^2) ~= 9.22
->
||v|| = sqrt(2^2 + -3.5^2) ~= 4.03
In fact we may choose to represent the vectors in a format that just directly says the angle with the X axis (i.e. direction) and magnitude, i.e. v could be written as {40.6 degrees, 9.22...} and u as {-56.32 degrees, 4.03...} (see also polar coordinates). This represents the same vectors, though we don't do this so often in programming.
A vector whose magnitude is exactly 1 is called a unit vector -- such vectors are useful in situations in which we only care about direction and not magnitude.
The vectors u and v may e.g. represent a velocity of cars in a 2D top-down racing game -- the vectors themselves will be used to update each car's position during one game frame and their magnitudes may be displayed as the current speed of each car to their drivers. However keep in mind the vector magnitude may also represent other things, e.g. in a 3D engine a vector may be used to represent camera's orientation and its magnitude may specify e.g. its field of view, or in a physics engine a vector may be used to represent a rotation (the direction specifies the axis of rotation, the magnitude specifies the angle of rotation).
But why not just use simple numbers? A velocity of a car could just as well be represented by two variables like carVelocityX
and carVelocityY
, why all this fuzz with defining vectors n shit? Well, this simply creates an abstraction that fits to many things we deal with and generalizes well, just like we e.g. define the concept of a sphere and cylinder even though fundamentally these are just sets of points. If for example we suddenly want to make a 3D game out of our racing game, we simply start using the vec3
data type instead of vec2
data type and most of our equation, such as that for computing speed, will stay the same. This becomes more apparent once we start dealing with more complex math, e.g. that related to physics where we have many forces, velocities, momenta etc. This becomes even more apparent when we start to look into operations with vectors which are really what makes vectors vectors.
Some of said operations with vectors include:
- addition (vector + vector = vector): Just like with numbers we can add vectors, i.e. for example if there are two forces acting on an object and we represent them by vectors, we can get the total force as a vector we get by adding the individual vectors. Addition is pretty straightforward, we simply add each component of both vectors, e.g. u + v = [7 + 2, 6 - 3.5] = [9,2.5]. Geometrically addition can be seen as drawing one vector from the other vector's endpoint (note that the order doesn't matter, i.e. u + v = v + u):
7 |
6 | _,
5 | __/|\u
4 | __/ \
3 | __/ \ u + v
2 | __/ __..--'/'
___1_|/_...--''____/____
-1 |\1 2 3 4__/6 7 8 9
-2 | \ __/
-3 | _\|/
-4 | "" v
-5 |
- subtraction (vector - vector = vector): Subtracting vector v from vector u is the same as adding v times -1 (i.e. v with opposite direction) to u.
- multiplication: There are several ways to "multiply" vectors.
- scalar multiplication (scalar * vector -> vector): Multiplying vector u with scalar x means scaling the vector v along its direction by the amount given by x -- for this we simply multiply each component of u by x, e.g. if x = 0.5, then u * x = [7 * 0.5,6 * 0.5] = [3.5,3].
- dot product (vector * vector -> scalar): Dot product of vectors u and v is a very common operation and can be used to determine the angle between the vectors, it is denoted as u . v and is computed as u . v = u.x * v.x + u.y * v.y + u.z * v.z + ...; the value this gives is the cosine of the angle between the vectors times the magnitude of u times the magnitude of v. I.e. if u and v have length of 1 (are normalized), we directly get the cosine of the angle and can get the angle with the acos function. This is used in many situations, e.g. in graphics shaders dot product is used to determine the angle at which light hits a surface which says how bright the surface will appear.
- cross product (vector * vector -> vector): Cross product basically gives us a vector that's perpendicular to the input vectors.
- vector matrix multiplication (vector * matrix -> vector): Multiplying a vector by matrix can achieve e.g. a specific transformation of the vector (such as rotating it). For details see the article about matrices.
- normalization: Normalization forces a vector's magnitude to a certain amount, typically 1 -- we do this when we have a vector and simply want to just discard its magnitude because we only care about direction (e.g. when doing a dot product to get an angle between vectors we first normalize them). To normalize a vector (to length 1) simply divide all its components by the current magnitude, e.g. normalized(u) = [u.x / ||u||,u.y / ||u||] = [0.76...,0.65...].
Code Example
TODO