// Header file for the Point class
// Created by:		Michael Edwards
// Date Started:	5/21/04
// Date Finished:	
// Complier Used:	Microsoft Visual C++, Version 6.0 Enterprise Edition

#ifndef MCL_POINT_H
#define MCL_POINT_H

#include <cassert>
#include <cmath>
#include <memory.h>

namespace MCL							// namespace for the Math Component Library
{
	template <class NumberType = float>
	class Point
	{
		public:
			Point(): dimension(0), coordinate(0)	{}
			// Default constructor

			Point(unsigned userDimension);
			// Creates a Point of size userDimension and initialized to 0
			// PRECONDITION:  none.
			// POSTCONDITION: creates a point at the origin of size userDimension
			
			Point(unsigned userDimension, NumberType* data);
			// Creates a Point of size userDimension and initialized to data
			// PRECONDITION:  size of data >= userDimension
			// POSTCONDITION: creates a point of size userDimension and 
			//				  initialized with data

			Point(const Point& rhs);
			// copy constructor
			
			virtual ~Point();
			// default destructor

			Point operator+(const Point& rhs) const;
			// the point is offsetted by rhs
			// PRECONDITION:  this->dimension == rhs.dimension
			// POSTCONDITION: this + rhs is returned

			Point operator-(const Point& rhs) const;
			// the point is negatively offsetted by rhs
			// PRECONDITION:  this->dimension == rhs.dimension
			// POSTCONDITION: this - rhs is returned
			
			Point operator*(NumberType rhs) const;
			// the point is scalar multiplied with rhs
			// PRECONDITION:  none.
			// POSTCONDITION: this * rhs is returned

			friend Point operator*(NumberType lhs, const Point& rhs);
			// the point, rhs, is scalar multiplied with lhs
			// PRECONDITION:  none.
			// POSTCONDITION: lhs * rhs is returned
			
			Point operator/(NumberType rhs) const;
			// the point is scalar divided with rhs
			// PRECONDITION:  rhs != 0.
			// POSTCONDITION: this / rhs is retured.
			
			Point& operator=(const Point& rhs);
			// assignment operator.
			// PRECONDITION:  none.
			// POSTCONDITION: this = rhs

			Point& operator+=(const Point& rhs);
			// adds rhs to this
			// PRECONDITION:  this->dimension == rhs.dimension
			// POSTCONDITION:

			Point& operator-=(const Point& rhs);
			// substracts rhs to this
			// PRECONDITION:  this->dimension == rhs.dimension
			// POSTCONDITION:

			Point& operator*=(NumberType rhs);
			// multiplies this by rhs
			// PRECONDITION:  none.
			// POSTCONDITION:

			Point& operator/=(NumberType rhs);
			// divides this by rhs
			// PRECONDITION:  rhs != 0.
			// POSTCONDITION:

			bool operator==(const Point& rhs) const;
			// checks to see if the points are equal starting from the first member to 
			// the pk member where k is the lower dimension of the two points
			// PRECONDITION:  none.
			// POSTCONDITION: checks to see if this == rhs

			bool operator!=(const Point& rhs) const;
			// checks to see if the points are not equal starting from the first member 
			// to the pk member where k is the lower dimension of the two points
			// PRECONDITION:  none.
			// POSTCONDITION: checks to see if this != rhs

			NumberType operator[](unsigned k) const;
			// grabs member pk from the coordinate set
			// PRECONDITION:  k: [0, dimension)
			// POSTCONDITION: pk is returned.

			NumberType& operator[](unsigned k);
			// grabs member pk from the coordinate set
			// PRECONDITION:  k: [0, dimension)
			// POSTCONDITION: pk is returned.

			NumberType FindDistance(const Point& rhs) const;
			// Finds the distance between this and rhs.
			// PRECONDITION:  this->dimension == rhs.dimension
			// POSTCONDITION: distance between the points is returned

			unsigned GetDimension() const	{ return dimension; }
			// Gets the dimension of the point
			// PRECONDITION:  none.
			// POSTCONDITION: the dimension is returned
			
			const NumberType* const ToFloat() const	{ return coordinate; }
			// Converts the point object to a NumberType array
			// PRECONDITION:  none.
			// POSTCONDITION: the NumberType array equivalent is returned

		private:
			NumberType*	coordinate;		// contains (p0, p1, p2, ..., pn)
			unsigned	dimension;		// dimension (n) of point
	};
}

#endif