#pragma once
#include "McGeVector3d.h"
#include "McArray.h"
class McGeMatrix3d;
class McGeLinearEnt3d;
class McGePlane;
class McGePlanarEnt;
class McGeVector3d;
class McGePoint2d;

// -------------------------------------------------------------------------
// Summary:
// 		McGePoint3d表示在3D空间中的点
// -------------------------------------------------------------------------
class MXGEDLL McGePoint3d
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McGePoint3d();
	// -------------------------------------------------------------------------
	// Summary:
	// 		拷贝构造函数
	// -------------------------------------------------------------------------
	McGePoint3d(const McGePoint3d& pnt);


	McGePoint3d(const McGePoint2d& pnt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		由x,y,z构造点
	// -------------------------------------------------------------------------
	McGePoint3d(double x, double y, double z);

	//:Ignore
	
	McGePoint3d(const McGePlanarEnt& pln, const McGePoint2d& pnt2d);
	//:End Ignore

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


	friend MXGEDLL
		McGePoint3d    operator *  (const McGeMatrix3d& mat, const McGePoint3d& pnt);

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

	// -------------------------------------------------------------------------
	// Summary:
	// 		使用矩阵变换该点。结果和setToProduct(leftSide, *this)
	// Parameters:
	// 		leftSide - 变换矩阵
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint3d&   transformBy (const McGeMatrix3d& leftSide);
	McGePoint3d&   transformBy_new(const McGeMatrix3d& leftSide);
	
	// -------------------------------------------------------------------------
	// Summary:
	// 		该点是绕向量vec,以wrtPoint为基点逆时针旋转ang角度。
	// Parameters:
	// 		angle		-	旋转角度
	//		wrtPoint	-	旋转中心
	//		vec			-	输入旋转轴线
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint3d&   rotateBy    (double angle, const McGeVector3d& vec,
		const McGePoint3d& wrtPoint = McGePoint3d::kOrigin);
	// -------------------------------------------------------------------------
	// Summary:
	// 		相对于pln平面镜向该点
	// Parameters:
	// 		pln -	镜向平面
	// Returns:
	// 		返回该对象的引用
	// -------------------------------------------------------------------------
	McGePoint3d&   mirror      (const McGePlane& pln);

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

	// -------------------------------------------------------------------------
	// Summary:
	// 		把3d变成2d点返回
	// -------------------------------------------------------------------------
	McGePoint2d    convert2d   (const McGePlane& pln) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		把3d点变成XY平面的点返回
	// -------------------------------------------------------------------------
	McGePoint2d    convertXYPlanar2d   () const;

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

	McGePoint3d    operator +  (const McGeVector3d& vec) const;
	McGePoint3d&   operator += (const McGeVector3d& vec);
	McGePoint3d    operator -  (const McGeVector3d& vec) const;
	McGePoint3d&   operator -= (const McGeVector3d& vec);
	McGePoint3d&   setToSum    (const McGePoint3d& pnt, const McGeVector3d& vec);

	
	McGeVector3d   operator -  (const McGePoint3d& pnt) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		用同样坐标设置转换3D点为3D矢量
	// -------------------------------------------------------------------------
	McGeVector3d   asVector    () const;


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


	McGePoint3d    project       (const McGePlane& pln, const McGeVector3d& vec) const;
	McGePoint3d    orthoProject  (const McGePlane& pln) const;


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

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


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

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置点的两个x,y,z坐标
	// -------------------------------------------------------------------------
	McGePoint3d&   set         (double x, double y, double z);
	McGePoint3d&   set         (const McGePlanarEnt& pln, const McGePoint2d& pnt);

	double lengthSqrd() const { return x * x + y * y + z * z; }

	double         x, y, z;
};


inline
McGePoint3d::McGePoint3d() : x(0.0), y(0.0), z(0.0)
{
}



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


inline
McGePoint3d::McGePoint3d(double xx, double yy, double zz) : x(xx), y(yy), z(zz)
{
}


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


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


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

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

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

inline McGePoint3d
McGePoint3d::operator + (const McGeVector3d& v) const
{
	return McGePoint3d (x + v.x, y + v.y, z + v.z);
}


inline McGePoint3d&
McGePoint3d::operator += (const McGeVector3d& v)
{
	x += v.x;
	y += v.y;
	z += v.z;
	return *this;
}


inline McGePoint3d
McGePoint3d::operator - (const McGeVector3d& v) const
{
	return McGePoint3d (x - v.x, y - v.y, z - v.z);
}


inline McGePoint3d&
McGePoint3d::operator -= (const McGeVector3d& v)
{
	x -= v.x;
	y -= v.y;
	z -= v.z;
	return *this;
}


inline McGeVector3d
McGePoint3d::operator - (const McGePoint3d& p) const
{
	return McGeVector3d (x - p.x, y - p.y, z - p.z);
}


inline McGeVector3d
McGePoint3d::asVector() const
{
	return McGeVector3d(x, y, z);
}

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

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

inline double&
McGePoint3d::operator [] (unsigned int i)
{
	return *(&x+i);
}
typedef McArray<McGePoint3d> McGePoint3dArray;

