#pragma once

#include "McGeContext.h"
#include "Mdesk.h"
#include "McGeVector2d.h"
#include "McArray.h"

class McGeMatrix2d;
class McGeLinearEnt2d;
class McGeLine2d;

class McGePoint3d;

// -------------------------------------------------------------------------
// Summary:
// 		McGePoint2d表示二维空间中的一个点实体
// -------------------------------------------------------------------------
class MXGEDLL McGePoint2d
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McGePoint2d(void);
	// -------------------------------------------------------------------------
	// Summary:
	// 		拷贝构造函数
	// -------------------------------------------------------------------------
	McGePoint2d(const McGePoint2d& pnt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		由x,y坐标构造点
	// -------------------------------------------------------------------------
	McGePoint2d(double x, double y);

	// -------------------------------------------------------------------------
	// Summary:
	// 		坐标原点
	// -------------------------------------------------------------------------
	static const   McGePoint2d kOrigin;

	friend
MXGEDLL	McGePoint2d    operator *  (const McGeMatrix2d& mat, const McGePoint2d& pnt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置该点等于矩阵mat 和点pnt的乘积的点。乘法公式为mat*pnt
	// Parameters:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint2d&   setToProduct(const McGeMatrix2d& mat, const McGePoint2d& pnt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		使用矩阵变换该点。结果和setToProduct(leftSide, *this)
	// Parameters:
	// 		leftSide - 变换矩阵
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint2d&   transformBy (const McGeMatrix2d& leftSide);

	// -------------------------------------------------------------------------
	// Summary:
	// 		该点是绕点wrtPoint逆时针旋转ang角度。
	// Parameters:
	// 		angle		-	旋转角度
	//		wrtPoint	-	旋转中心
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint2d&   rotateBy    (double angle, const McGePoint2d& wrtPoint
		= McGePoint2d::kOrigin);

	// -------------------------------------------------------------------------
	// Summary:
	// 		相对于line线镜向该点
	// Parameters:
	// 		line -	镜向直线
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint2d&   mirror      (const McGeLine2d& line);

	// -------------------------------------------------------------------------
	// Summary:
	// 		以wrtPoint原点，scaleFactor缩放该点
	// Parameters:
	// 		scaleFactor -	输入比例因子
	//		wrtPoint	-	输入缩放中心
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint2d&   scaleBy     (double scaleFactor, const McGePoint2d& wrtPoint
		= McGePoint2d::kOrigin);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回等于由比例因子val缩放的这个点的点
	// Parameters:
	// 		val - 缩放比例
	// -------------------------------------------------------------------------
	McGePoint2d    operator *  (double val) const;
	friend
		McGePoint2d    operator *  (double, const McGePoint2d& scl);
	McGePoint2d&   operator *= (double scl);
	McGePoint2d    operator /  (double scl) const;
	McGePoint2d&   operator /= (double scl);

	McGePoint2d    operator +  (const McGeVector2d& vec) const;
	McGePoint2d&   operator += (const McGeVector2d& vec);
	McGePoint2d    operator -  (const McGeVector2d& vec) const;
	McGePoint2d&   operator -= (const McGeVector2d& vec);
	McGePoint2d&   setToSum    (const McGePoint2d& pnt, const McGeVector2d& vec);

	McGeVector2d   operator -  (const McGePoint2d& pnt) const;


	inline const McGeVector2d& asVector() const
	{
		return *reinterpret_cast<const McGeVector2d*>(this);
	}

	// -------------------------------------------------------------------------
	// Summary:
	// 		求两个点距离
	// Parameters:
	// 		pnt - 另一个点
	// -------------------------------------------------------------------------
	double         distanceTo  (const McGePoint2d& pnt) const;

	Mdesk::Boolean operator == (const McGePoint2d& pnt) const;
	Mdesk::Boolean operator != (const McGePoint2d& pnt) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		判断两个点是否相等
	// -------------------------------------------------------------------------
	Mdesk::Boolean isEqualTo   (const McGePoint2d& pnt,
		const McGeTol& tol = McGeContext::gTol) const;


	double         operator [] (unsigned int i) const;
	double&        operator [] (unsigned int idx);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置点的x,y坐标
	// -------------------------------------------------------------------------
	McGePoint2d&   set         (double x, double y);

	// -------------------------------------------------------------------------
	// Summary:
	// 		把点变成一个3d点返回
	// -------------------------------------------------------------------------
	McGePoint3d    Point3d() const;

	double         x, y;
};


inline
McGePoint2d::McGePoint2d() : x(0.0), y(0.0)
{
}

inline
McGePoint2d::McGePoint2d(const McGePoint2d& src) : x(src.x), y(src.y)
{
}

inline
McGePoint2d::McGePoint2d(double xx, double yy) : x(xx), y(yy)
{
}

inline McGePoint2d
McGePoint2d::operator * (double val) const
{
	return McGePoint2d(x*val, y*val);
}

inline McGePoint2d
operator * (double val, const McGePoint2d& p)
{
	return McGePoint2d(p.x*val, p.y*val);
}


inline McGePoint2d&
McGePoint2d::operator *= (double val)
{
	x *= val;
	y *= val;
	return *this;
}

inline McGePoint2d
McGePoint2d::operator / (double val) const
{
	return McGePoint2d (x/val, y/val);
}

inline McGePoint2d&
McGePoint2d::operator /= (double val)
{
	x /= val;
	y /= val;
	return *this;
}


inline McGePoint2d
McGePoint2d::operator + (const McGeVector2d& v) const
{
	return McGePoint2d(x + v.x, y + v.y);
}


inline McGePoint2d&
McGePoint2d::operator += (const McGeVector2d& v)
{
	x += v.x;
	y += v.y;
	return *this;
}


inline McGePoint2d
McGePoint2d::operator - (const McGeVector2d& v) const
{
	return McGePoint2d(x - v.x, y - v.y);
}


inline McGePoint2d&
McGePoint2d::operator -= (const McGeVector2d& v)
{
	x -= v.x;
	y -= v.y;
	return *this;
}


inline McGeVector2d
McGePoint2d::operator - (const McGePoint2d& p) const
{
	return McGeVector2d(x - p.x, y - p.y);
}



inline McGePoint2d&
McGePoint2d::set(double xx, double yy)
{
	x = xx;
	y = yy;
	return *this;
}

inline double
McGePoint2d::operator [] (unsigned int i) const
{
	return *(&x+i);
}

inline double&
McGePoint2d::operator [] (unsigned int i)
{
	return *(&x+i);
}

typedef McArray<McGePoint2d> McGePoint2dArray;