3D Vectors | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||||||||||||
Download: |
|
|||||||||||||||
An Introduction to Vectors
The word 'Vector' is used to describe several things in computing. In this instance, it means a journey. The journey can be described in two or three dimensions and depends upon knowing the axes that are being used, just like a knowing which way is North when using a map. You can describe a journey on a map by saying that you moved two squares East and three squares North. A vector does not say where you started from! For that you would need a gPoint class as well (the gPV classes are a Point and Vector in the same class). You can add vectors just as you can do a journey multiple times: if you go two squares East and three North and then do the same again, you end up being four squares East and six North of wherever you started.
So adding vectors is simply adding their components. Subtracting is just going back the other way. Multiplying and dividing by a number are scaling 2*(2,2)=(4,4); and (4,4)/2=(2,2);In two dimensions, the components are often called dx and dy, with a dz in three dimensions. The 'd' is for delta usually meaning a change. The classes presented here share a base class with the gPoint classes and so the components are simply x and y, with a z in g3Vector.
A vector has a length that you get using the Pythagorean theorem: Length=sqrt(x*x+y*y); (or Length=_hypot(x,y); using <math.h>). The journey "two squares East and three squares North" is describing two sides of a right-angled triangle, the journey as the crow flies is the hypotenuse. Another useful thing to know is that the square root of 2 (M_SQRT2 in <math.h>) is the length of the hypotenuse of a unit square... So a square with side length=2 has a diagonal of length 2*M_SQRT2;
Quite often vectors are just used to indicate a direction, and the maths gets simpler if those have a length of one. These 'Unit-Vectors' are made simply by dividing each component by the length of the vector; a process called Normalising/Normalizing.
Can you multiply two vectors? Vectors have two beautiful methods that help make all sorts of things easier called the Dot and Cross Products, or Scalar and Vector Products (referring to the values they return). Both methods take two vectors as parameters, are very fast and are different takes on multiplication. The Dot product returns a double which can be used in all sorts of ways to indicate how the two vectors relate to each other. This is great for projecting things like points on to lines or planes, or seeing which side of a line a point is. The Cross product returns another vector which (in three dimensions) is perpendicular to the two other vectors. This is perfect for finding the normal of a plane or creating new axes. If you have a geometry problem: always start looking for a solution with these two methods first: they're both really fast compared to any trigonometry. To get a proper feel for the dot product, play on this page: Dot Product.
g3Vector and g2Vector
The vector structs control two or three gCoords.
g3Vector and g2Vector have most of the usual functions: GetLength, Dot, Cross and Triple Products (CrossDot, MakeAxis and GetAxis).
GetL2 returns the length squared; this saves a sqrt and is often used in trigonometry.
There are methods to Reverse and Project the vector; Colinear compares two vectors and there's SameX,SameY and SameZ.
g2Vector::cwTo(const g2Vector& V) effectively returns the z component of the Cross Product as a quick way to test for clockwiseness (Assumes Right Hand Screw Rule and 2D).
The operator bool() in g3D and g2D makes it easy to check the validity of Vectors (false means the Vector has all zero values).
A couple of the methods need more explanation...
SetLength is worth pointing out: it uses the vector just for its direction information, and sets the length. People don't seem to expect that method to be there.
Normalise and Normalised can both take a Tolerance parameter which snaps the result to one of the Global Axes if the unit vector has a component within the tolerance of ±1.
This helps make sure that rounding errors don't stop vertical things being vertical and horizontal things being horizontal.
Creating Axes from a given Vector
GetPerpendicular is useful for 3D Planes where the vector is the Plane Normal, and you want a Vector on the Plane.
GetAxes is similar to GetPerpendicular but provides two axes on the plane from the vector provided which is taken to be the Z-Axis.
HorizontalAxisType and Try4Axis help describe how these Axes should be created.
They are not trivial to understand and for most applications you can ignore them. This will result in the X-axis being horizontal... but it could be horizontal in either of two directions: one where the Y-axis points up, and one where it points down... the default is the Y-axis will point so that as you look down the X-axis, the Z-axis is anti-clockwise from the global Z-axis (rotating about the X-axis)!
If you want or need more control, for robotics, for example, read on:
When given a Z-Axis, you can specify which of X or Y are to be horizontal using the HorizontalAxisType enum.
Looking down the local horizontal axis to the origin, the local Z-Axis (this vector) is either anti-clockwise (default) or clockwise from Vertical (rotating around the horizontal Axis).
If you set Try4Axis you are saying, if the horizontal axis is anti-parallel with it's Global equivalent, make it parallel. This overrides HorizontalAxisType
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.