Part 4 of C++ tutorial – a 3D vector & transform library
The classic vector operations are the dot & cross products.
Here are the respective helper functions:
double dot_product(const Vector& v) const { return x*v.x+y*v.y+z*v.z; }
Vector cross_product(const Vector& v) const { return Vector(y*v.y-v.y*z,v.x*z-x*v.y,x*v.y-v.x*y); }
The dot product returns a scalar, whereas the cross product returns a vector (more specifically, a normal).
For the dot operation, one might think one could try and overload the dot operator (not legal C++), but it is a member selection operator rather than an arithmetic one, so its semantics don’t map. However, we could overload the multiply operator, but it is not clear whether it should indicate dot or cross product. To maintain clarity, it’s probably best if dot and cross products are named explicitly.
One could provide friend functions taking two arguments, e.g. dot_product(u,v)
. However, I think it’s going to provide greater clarity upon use if member functions taking single arguments are used, e.g. u.dot(v)
. That way, more complicated expressions are easier to read, e.g. (<vector expression>).dot(<vector expression>)
vs dot_product(<vector expression>,<vector expression>).
As they are acting as operators (as opposed to public methods), I’m inclined to name them in lower case.
Therefore the Vector methods for dot and cross products are:
double dot(const Vector& v) const { return dot_product(v); }
Vector cross(const Vector& v) const { return cross_product(v); } // NB Result is Normal vector
For example:
cout<<"u.v="<<u.dot(v)<<"\n";
cout<<"u x v="<<u.cross(v)<<"\n";
Which outputs:
u=(1,2,3)
v=(-1,3,-6)
u.v=-13
u x v=(-3,-6,5)
Complete code:
#include <iostream> // For console output functionality
using namespace std; // Avoids having to use std:: scoping prefix
class Vector // A vector class with addition and subtraction functionality
{
public:
double x,y,z; // Representation
protected:
// Non-modifying functions
Vector addition(const Vector& v) const { return Vector(x+v.x,y+v.y,z+v.z); }
Vector subtraction(const Vector& v) const { return Vector(x-v.x,y-v.y,z-v.z); }
Vector multiplication(double m) const { return Vector(x*m,y*m,z*m); }
Vector division(double d) const { if (d) return Vector(x/d,y/d,z/d); else throw std::runtime_error("Divide by Zero"); }
double dot_product(const Vector& v) const { return x*v.x+y*v.y+z*v.z; }
Vector cross_product(const Vector& v) const { return Vector(y*v.y-v.y*z,v.x*z-x*v.y,x*v.y-v.x*y); }
// Modifying methods
void assign(const Vector& v) { x=v.x; y=v.y; z=v.z; }
void add(const Vector& v) { assign(addition(v)); }
void subtract(const Vector& v) { assign(subtraction(v)); }
void multiply_by(double m) { assign(multiplication(m)); }
void divide_by(double d) { assign(division(d)); }
public:
Vector(double a,double b,double c):x(a),y(b),z(c) { }
double dot(const Vector& v) const { return dot_product(v); }
Vector cross(const Vector& v) const { return cross_product(v); }
Vector& operator+=(const Vector& v) { add(v); return *this; }
Vector& operator-=(const Vector& v) { subtract(v); return *this; }
friend Vector operator+(const Vector& u,const Vector& v) { return Vector(u.addition(v)); }
friend Vector operator-(const Vector& u,const Vector& v) { return Vector(u.subtraction(v)); }
Vector& operator*=(double m) { multiply_by(m); return *this; }
Vector& operator/=(double d) { divide_by(d); return *this; } // Throws div0
friend Vector operator*(const Vector& v,double m) { return Vector(v.multiplication(m)); }
friend Vector operator*(double m,const Vector& v) { return Vector(v.multiplication(m)); }
friend Vector operator/(const Vector& v,double d) { return Vector(v.division(d)); }
friend ostream& operator<<(ostream& os,const Vector& v)
{ return os<<'('<<v.x<<','<<v.y<<','<<v.z<<')'; } // Output, e.g. (1,2,3)
};
int main() // The program
{ Vector u(1,2,3); // A test vector
Vector v(-1,3,-6); // A test vector
cout<<"u="<<u<<"\n";
cout<<"v="<<v<<"\n";
cout<<"u.v="<<u.dot(v)<<"\n";
cout<<"u x v="<<u.cross(v)<<"\n";
}
Comments
There are currently no comments on this article.
Comment