//------------------------------------------------------------------------------
// Author:		Gero Mueller <gero.mueller@cloo.de>
// Copyright:	(c) 2006 Gero Mueller
// License:		MIT License
//------------------------------------------------------------------------------

#ifndef BLUECORE_RAY_H
#define BLUECORE_RAY_H

#include "scalar.h"
#include "vector.h"

namespace BlueCore
{
	template <class T>
	class RayTemplate
	{
		Vector3Template<T> point, direction;

	public:
	
		/**
		 * normalize the vector to length 1
		 */
		inline RayTemplate()
		{
		}


		/**
		 * constructor from point and direction
		 */
		template <class S>
		inline RayTemplate(
			const Vector3Template<S> &point,
			const Vector3Template<S> &direction )
		{
			this->point = point;
			this->direction = direction.normalized();
		}


		/**
		 * set the point
		 */
		template <class S>
		inline setPoint( const Vector3Template<S> &point )
		{
			this->point = point;
		}


		/**
		 * set the direction
		 */
		template <class S>
		inline setDirection( const Vector3Template<S> &direction )
		{
			this->direction = direction.normalized();
		}


		/**
		 * get point
		 */
		inline const Vector3Template<T> &getPoint() const
		{
			return point;
		}


		/**
		 * get direction
		 */
		inline const Vector3Template<T> &getDirection() const
		{
			return direction;
		}


		/**
		 * checks if a point lies on the ray
		 */
		template <class S>
		inline bool contains( const Vector3Template<T> &a )
		{
			return (a - point).parallel( direction );
		}
		
		/**
		 * calculate the distance between a point and the ray
		 */
		template <class S>
		inline T distance( const Vector3Template<S> &a ) const
		{
			T t = direction.dot( a - point );
			Vector3Template<T> b = at(t) - a;
			return b.length();
		}


		/**
		 * gets the position at distance t
		 */
		template <class S>
		inline Vector3Template<S> at( const T a ) const
		{
			return Vector3Template<T>( point + direction * a );
		}


	};
	
	typedef RayTemplate<float> RayFloat;
	typedef RayTemplate<double> RayDouble;
	typedef RayTemplate<Scalar> Ray;
}

#endif
