//
//	Copyright © 2005 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#pragma once

namespace VWFC
{
	namespace Math
	{
		// --------------------------------------------------------------------------------
		class VWPoint2D
		{
		public:
			// construction
						VWPoint2D();
						VWPoint2D(const WorldPt& src);
						VWPoint2D(double x, double y);
						VWPoint2D(const VWPoint2D& src);
						~VWPoint2D();

			void		SetPoint(const WorldPt& pt);
			void		SetPoint(double x, double y);
			void		SetAngle(double radians);
			void		SetPointByAngle(double degAng, double length);

			// assignments
			VWPoint2D&	operator=(const VWPoint2D& src);
			VWPoint2D&	operator=(const WorldPt& src);

			bool		operator==(const VWPoint2D& p) const;
			bool		operator!=(const VWPoint2D& p) const;

			VWPoint2D	operator+(const VWPoint2D& p) const;
			VWPoint2D	operator-(const VWPoint2D& p) const;
			VWPoint2D	operator*(double scalar) const;
			VWPoint2D	operator/(double scalar) const;
			// dot product
			double		operator%(const VWPoint2D& p) const;
			
			VWPoint2D	operator-(void) const;
	
			VWPoint2D&	operator+=(const VWPoint2D& p);
			VWPoint2D&	operator-=(const VWPoint2D& p);
			VWPoint2D&	operator*=(double scalar);
			VWPoint2D&	operator/=(double scalar);

			// compatibility with SDK
							operator const WorldPt&() const;

		// Math functions
		public:
			// return the distance from (0,0) to this point
			double			Magnitude() const;
			// return true if the specified point is equal within the given epsilon to this point
			bool			Equal(const VWPoint2D& pt, double dEpsilon) const;
			// calculate the distance from the specified point to this point
			double			DistanceTo(double x, double y) const;
			double			DistanceTo(const VWPoint2D& pt) const;
			// rotate this point at specified angle in degrees and center point
			void			RotateAtDeg(const VWPoint2D& centerPt, double_gs dDegAngle);
			// rotate this point at specified angle in radians and center point
			void			RotateAtRad(const VWPoint2D& centerPt, double_gs dRadAngle);
			// return perpendicular point of this point
			VWPoint2D		Perp() const;
			// set this point to the perpendicullar of the specified point
			void			Perp(const VWPoint2D& pt);
			// get the angle of this point's vector from -180 to 180 deg
			double			CalcAng180() const;
			// get the angle of this point's vector from 0 to 360 deg
			double			CalcAng360() const;
			// set this points as the center of a circle passing thru 3 given points
			void			ThreePtCenter(const VWPoint2D& pt1, const VWPoint2D& pt2, const VWPoint2D& pt3);
			// translates this point into a coordinate system defined by 2 other points.
			void			RelativeCoords(const VWPoint2D& pt1, const VWPoint2D& pt2);
			// Cross product magnitude is primarily used for determining the left/right orientation of two vectors.
			double			CrossProductMagnitude(const VWPoint2D& pt) const;
			//The mathematical definition of Dot Product is:
			//		|a||b|cos theta or 
			//		the magnitude of 'a' times the magnitude of 'b' times the cosine of the angle between 'a' and 'b'
			double			DotProduct(const VWPoint2D& pt) const;
			// normalize this vector
			VWPoint2D&		Normalize();
			// whether the current point is on the left of vector provided as parameter
			bool			IsPointOnTheRightOfVector(const VWPoint2D& vec) const;
			
		// data
		public:
			double		x, y;

		// static point funtions
		public:
			// default epsilon for operator==
			static double	sEpsilon;
			// area is negative if the triangle is CCW
			static double	TriArea(const VWPoint2D& pt1, const VWPoint2D& pt2, const VWPoint2D& pt3);
			// area is negative if the triangle is CCW
			static double	TriArea(double pt1x, double pt1y,
									double pt2x, double pt2y,
									double pt3x, double pt3y);
			static double	Distance(double x1, double y1, double x2, double y2);

		private:
			WorldPt		fPoint;
		};

		// array of point defintion
		typedef		std::vector<VWPoint2D>									TSTLPoints2DArray;
		typedef		std::vector<VWPoint2D, std::vwallocator<VWPoint2D> >	TSTLPoints2DVWArray;
	}
}