Vector Products: Dot & Cross

Posted
Comments 0

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";

}

Author

Comments

There are currently no comments on this article.

Comment

Enter your comment below. Fields marked * are required. You must preview your comment before submitting it.