// Programmer: Josh Santomieri
// http://www.santsys.com
// Example of simple 2 point vector class with operator overides

#include <iostream.h>
#include <math.h>

template<class T>
class CVect
{
public:
	CVect();
	CVect(T x, T y, T z);
	~CVect();

	void SetVect(T x, T y, T z);
	void SetVectX(T x);
	void SetVectY(T y);
	void SetVectZ(T z);
	void PrintVect();
	double Distance(CVect<T> V1);

	CVect<T> operator+(CVect<T> &V1);
	CVect<T> operator-(CVect<T> &V1);
	CVect<T> operator*(CVect<T> &V1);
	CVect<T> operator/(CVect<T> &V1);
	int operator==(CVect<T> &V1);
	int operator!=(CVect<T> &V1);

private:
	T x;
	T y;
	T z;
};

template<class T>
CVect<T>::CVect()
{
}

template<class T>
CVect<T>::CVect(T x, T y, T z)
{
	CVect::x = x;
	CVect::y = y;
	CVect::z = z;
}

template<class T>
CVect<T>::~CVect()
{
}

template<class T>
void CVect<T>::SetVect(T x = 0, T y = 0, T z = 0)
{
	CVect::x = x;
	CVect::y = y;
	CVect::z = z;
}

template<class T>
void CVect<T>::PrintVect()
{
	cout << "(" << CVect::x << ", " << CVect::y << ", " << CVect::z << ")" <<endl;
}

template<class T>
void CVect<T>::SetVectX(T x)
{
	CVect::x = x;
}

template<class T>
void CVect<T>::SetVectY(T y)
{
	CVect::y = y;
}

template<class T>
void CVect<T>::SetVectZ(T z)
{
	CVect::z = z;
}

template<class T>
double CVect<T>::Distance(CVect<T> V1)
{
	double dDist = 0.0;

	dDist = (sqrt((pow((CVect::x - V1.x), 2) + pow((CVect::y - V1.y), 2)) + pow((CVect::z - V1.z), 2)));

	return dDist;
}

template<class T>
CVect<T> CVect<T>::operator+(CVect<T> &V1)
{
	CVect<T> temp;
	temp.x = CVect::x + V1.x;
	temp.y = CVect::y + V1.y;
	temp.z = CVect::z + V1.z;

	return temp;
}

template<class T>
CVect<T> CVect<T>::operator-(CVect<T> &V1)
{
	CVect<T> temp;
	temp.x = CVect::x - V1.x;
	temp.y = CVect::y - V1.y;
	temp.z = CVect::z - V1.z;

	return temp;
}

template<class T>
CVect<T> CVect<T>::operator*(CVect<T> &V1)
{
	CVect<T> temp;
	temp.x = CVect::x * V1.x;
	temp.y = CVect::y * V1.y;
	temp.z = CVect::z * V1.z;

	return temp;
}

template<class T>
CVect<T> CVect<T>::operator/(CVect<T> &V1)
{
	CVect<T> temp;

	if((V1.x == 0) || (V1.y == 0) || (V1.z == 0))
		return NULL;
	else
	{
		temp.x = CVect::x / V1.x;
		temp.y = CVect::y / V1.y;
		temp.z = CVect::z / V1.z;
	}

	return temp;
}

template<class T>
int CVect<T>::operator==(CVect<T> &V1)
{
	return ((CVect::x == V1.x) && (CVect::y == V1.y) && (CVect::z == V1.z));
}

template<class T>
int CVect<T>::operator!=(CVect<T> &V1)
{
	return ((CVect::x != V1.x) || (CVect::y != V1.y) || (CVect::z == V1.z));
}

int main(int argc, char **argv)
{
	CVect<int> cv(1,2,3);
	CVect<int> cv1(3,4,5);
	CVect<double> cvd(1.1, 1.2, 1.3);
	CVect<double> cvd1(1.1, 2.2, 3.3);

	cvd.PrintVect();
	cv.PrintVect();
	cv1.PrintVect();

	cv = cv + cv1;
	cv.PrintVect();
	cvd = cvd + cvd1;
	cvd.PrintVect();

	cout << "distance (cv, cv1): " << cv.Distance(cv1) << endl;

	return 0;
}