//////////////////////////////////////////////////////////////////////////
//	class Point3d
//////////////////////////////////////////////////////////////////////////
class point
{
public:
	point point();
	~point();
	point point(const point & i_pt);	
	point point(double x = 0.0, double y = 0.0, double z = 0.0);
	point point(CString s);
	point operator =(const point& v_Param);
	point operator +=(const point& v_Param);
	point operator +(const point& v_Param);
	point operator -(const point& v_Param);
	point operator -=(const point& v_Param);

	double operator *(const point& pt);
	point operator *(double d);
	point operator *(const point& v_Param, double d);
	point operator *(double d, const point& v_Param);
	point operator *(int d, const point& v_Param);
	point operator /(double d);
	
	bool operator ==(const point& v_Param) const;
	bool operator !=(const point& v_Param) const;

	GetDataToString(CString &s);
	SetDataToString(CString s);
	
public:	
	double x;
	double y;
	double z;
};

//---------------------------------------------------------------------------------
double g_dStartX, g_dStartY, g_dStartZ;
g_dStartX = g_dStartY = g_dStartZ = 0.0;
point point::point()
{
	x=g_dStartX;
	y=g_dStartY;
	z=g_dStartZ;

	return *this;
}

point::~point()
{
}

point point::point(CString s)
{
	SetDataToString(s);
	
	return *this;
}

point point::point(const point & i_pt)
{
	x = i_pt.x;
	y = i_pt.y;
	z = i_pt.z;

	return *this;
}

point point::point(double v_x,double v_y,double v_z)
{
	x=v_x + g_dStartX;
	y=v_y + g_dStartY;
	z=v_z + g_dStartZ;

	return *this;
}

point point::operator =(const point& v_Param)
{	
	x=v_Param.x;
	y=v_Param.y;
	z=v_Param.z;
	
	return *this;
}

point point::operator +=(const point& v_Param)
{
	x+=v_Param.x;
	y+=v_Param.y;
	z+=v_Param.z;
	
	return *this;	
}

point point::operator +(const point& v_Param)
{
	point ptTemp;

	ptTemp.x = x + v_Param.x;
	ptTemp.y = y + v_Param.y;
	ptTemp.z = z + v_Param.z;
	
	return ptTemp;
}

point point::operator -(const point& v_Param)
{
	point ptTemp;
	
	ptTemp.x = x - v_Param.x;
	ptTemp.y = y - v_Param.y;
	ptTemp.z = z - v_Param.z;
	
	return ptTemp;
}

point point::operator -=(const point& v_Param)
{
	x-=v_Param.x;
	y-=v_Param.y;
	z-=v_Param.z;
	
	return *this;
}

point point::operator *(double d)
{
	point ptTemp;
	
	ptTemp.x = x * d;
	ptTemp.y = y * d;
	ptTemp.z = z * d;
	
	return ptTemp;
}

double point::operator *(const point& pt)
{
	double dRet = (y*pt.z - z*pt.y) + (z*pt.x - x*pt.z) + (x*pt.y - y*pt.x);	

	if(dRet < ZERO)
	{
		point ptTemp = point(x+pt.x, y+pt.y, z+pt.z);		
		dRet = GetLength(ptTemp, point()) - GetLength(*this, point());
	}

	return dRet;
}

point point::operator *(const point& v_Param, double d)
{
	point ptTemp;
	
	ptTemp.x = v_Param.x * d;
	ptTemp.y = v_Param.y * d;
	ptTemp.z = v_Param.z * d;
	
	return ptTemp;
}

point point::operator *(double d, const point& v_Param)
{
	point ptTemp = v_Param;
	
	ptTemp.x = v_Param.x * d;
	ptTemp.y = v_Param.y * d;
	ptTemp.z = v_Param.z * d;
	
	return ptTemp;
}

point operator *(int d, const point& v_Param)
{
	point ptTemp = v_Param;
	
	ptTemp.x = v_Param.x * d;
	ptTemp.y = v_Param.y * d;
	ptTemp.z = v_Param.z * d;
	
	return ptTemp;
}

point point::operator /(double d)
{
	point ptTemp = *this;
	
	if(d > ZERO)
	{
		ptTemp.x = x / d;
		ptTemp.y = y / d;
		ptTemp.z = z / d;
	}
	
	return ptTemp;
}


bool point::operator !=(const point& v_Param) const
{
	if(fabs(x - v_Param.x) > ZERO) return 1;
	if(fabs(y - v_Param.y) > ZERO) return 1;
	if(fabs(z - v_Param.z) > ZERO) return 1;
	
	return 0;
}

bool point::operator ==(const point& v_Param) const
{
	return !(*this != v_Param);
}

void setCenterPoint(point pt)
{
	g_dStartX = pt.x;
	g_dStartY = pt.y;
	g_dStartZ = pt.z;
}

point getCenterPoint()
{
	return point(g_dStartX, g_dStartY, g_dStartZ);
}

void point_set(point ptSc, point &ptDe)
{
	ptDe = ptSc;
}

//////////////////////////////////////////////////////////////////////////
//Geo
//////////////////////////////////////////////////////////////////////////
//取得两个点之间(直线)的长度
double GetLength(point ptStart,point ptEnd, int i_b3D = 1);	

//取得两个点之间(直线)的长度
//输入参数:const AcGePoint2d ptSt 组成直线的起点
//         const AcGePoint2d ptEd   组成直线的终点
double GetLength(point ptSt,point ptEd, int i_b3D)
{	
	double dDist;
	dDist=pow(ptEd.x-ptSt.x,2)+pow(ptEd.y-ptSt.y,2);
	
	if(i_b3D > 0)
		dDist += pow(ptEd.z - ptSt.z, 2);
	
	LJSQR(dDist)
		return dDist;
}

point ProjectPoint(point ptSt, point ptEd, point ptActive)
{
	if(GetLength(ptSt,ptEd)<ZERO)
		return ptSt;
	double dLineSt=GetLength(ptActive,ptSt);
	double dLineEd=GetLength(ptActive,ptEd);
	double dLineSE=GetLength(ptSt,ptEd);
	double dS1=(dLineSt+dLineEd+dLineSE)/2.0;
	double dS=dS1*(dS1-dLineSt)*(dS1-dLineEd)*(dS1-dLineSE);
	LJSQR(dS)
		double dUpRight=dS*2.0/dLineSE;
	double dM1=pow(dLineSt,2)-pow(dUpRight,2);
	double dM2=pow(dLineEd,2)-pow(dUpRight,2);
	LJSQR(dM1)
		LJSQR(dM2)	
		point UpRightPt;	
	if(dM1>dLineSE||dM2>dLineSE)
	{
		if(fabs(dM1-dM2)>ZERO)
		{
			UpRightPt.x=(dM2*ptSt.x-dM1*ptEd.x)/(dM2-dM1);
			UpRightPt.y=(dM2*ptSt.y-dM1*ptEd.y)/(dM2-dM1);
			UpRightPt.z=(dM2*ptSt.z-dM1*ptEd.z)/(dM2-dM1);
		}			
	}		
	else
	{
		if(fabs(dM1+dM2)>ZERO)
		{
			UpRightPt.x=(dM2*ptSt.x+dM1*ptEd.x)/(dM1+dM2);
			UpRightPt.y=(dM2*ptSt.y+dM1*ptEd.y)/(dM1+dM2);
			UpRightPt.z=(dM2*ptSt.z+dM1*ptEd.z)/(dM1+dM2);
		}
	}
	return UpRightPt;
}

//取得直线的斜率
//输入参数:point ptSt 组成直线的起点
//         point ptEd   组成直线的终点
//         double& o_dSlope   求得斜率保存单元,如果o_bInfinite=1该值无意义
//         bool&   o_bInfinite  如果为无穷大,返回1,否则0
void slope(point ptSt, point ptEd, double& o_dSlope, bool& o_bInfinite)
{
	double dAngle=GetAngle(ptSt,ptEd);
	if(fabs(dAngle-PI/2)<=ZERO || fabs(dAngle-3*PI/2)<=ZERO)
	{
		o_dSlope=1000000;
		o_bInfinite=1;	
	}
	else
	{
		o_bInfinite=0;
		o_dSlope=tan(dAngle);
	}
	if(fabs(o_dSlope)<ZERO)
		o_dSlope=0;
}


//函数功能:判断一个点是否在一条直线上
//输入参数:point ptSt  组成直线的起点
//         point ptEd    组成直线的终点
//         point ptActive 要判断的点
//返回参数:1 在,0 在延长线上,-1不在
int PtInLine(point ptSt, point ptEd, point ptActive)
{
	if(GetLength(ptSt,ptActive)<ZERO||
		GetLength(ptEd,ptActive)<ZERO)
		return 1;
	if(GetLength(ptSt,ptEd)<ZERO)
		return -1;
	
	double dXl1=0.0;
	if(fabs(ptEd.x-ptSt.x)>ZERO)
		dXl1=(ptEd.y-ptSt.y)/(ptEd.x-ptSt.x);
	
	double dXl2=0.0;
	if(fabs(ptActive.x-ptSt.x)>ZERO)
		dXl2=(ptActive.y-ptSt.y)/(ptActive.x-ptSt.x);
	
	if(fabs(dXl2-dXl1)<ZERO)
	{
		if(fabs(ptSt.x-ptEd.x)<ZERO)
		{
			if(ptSt.y<ptEd.y)
			{
				if(ptActive.y-ZERO<ptEd.y&&ptActive.y+ZERO>ptSt.y)
					return 1;
				else
					return 0;
			}
			else
			{
				if(ptActive.y+ZERO>ptEd.y&&ptActive.y-ZERO<ptSt.y)
					return 1;
				else
					return 0;
			}
		}
		else
		{
			if(ptSt.x<ptEd.x)
			{
				if(ptActive.x-ZERO<ptEd.x&&ptActive.x+ZERO>ptSt.x)
					return 1;
				else
					return 0;
			}
			else
			{
				if(ptActive.x+ZERO>ptEd.x&&ptActive.x-ZERO<ptSt.x)
					return 1;
				else
					return 0;
			}
		}
		
	}
	else
		return -1;
}


//程序功能:判断两条直线是否相交，并取得两条直线的交点
//返回参数: 2 - 重叠相交; 1 - 表示两线段内相交; 0 - 表示两线段在延长线上相交; -1 表示不相交
//输入参数:point pt1St,			第一条直线的起点
//		   point pt1Ed,			第一条直线的终点
//		   point pt2St,			第二条直线的起点
//         point pt2Ed,			第二条直线的终点
//		   point& o_ptInter     交点
int intersect(point pt1St, point pt1Ed, point pt2St, point pt2Ed, point& o_ptInter)
{
	double Slope1=0,Slope2=0; //斜率
	bool isInfinite1=0;
	bool isInfinite2=0;

	slope(pt1St,pt1Ed,Slope1,isInfinite1);
	slope(pt2St,pt2Ed,Slope2,isInfinite2);

	if(fabs(Slope1-Slope2)<=ZERO) //平行
	{
		if( PtInLine(pt1St,pt1Ed,pt2St)  ==1 ||
		    PtInLine(pt1St,pt1Ed,pt2Ed)    ==1 ||
		    PtInLine(pt2St,pt2Ed,pt1St) ==1 ||
		    PtInLine(pt2St,pt2Ed,pt1Ed)   ==1 )
		{
			double Len1=GetLength(pt1St,pt1Ed);
			double Len2=GetLength(pt1St,pt2St);
			double Len3=GetLength(pt1St,pt2Ed);
			double Len4=GetLength(pt1Ed,pt2St);
			double Len5=GetLength(pt1Ed,pt2Ed);
			double Len6=GetLength(pt2St,pt2Ed);
			
			double Length1=GetLength(pt1St,pt1Ed);
			double Length2=GetLength(pt2St,pt2Ed);
			double Length = Len1;
			Length = Length > Len2 ? Length : Len2;
			Length = Length > Len3 ? Length : Len3;
			Length = Length > Len4 ? Length : Len4;
			Length = Length > Len5 ? Length : Len5;
			Length = Length > Len6 ? Length : Len6;		
			//重合
			if((Length+ZERO)<(Length1+Length2))
				return 2;
		}
		//检查两条线是否首尾相接
		if( pt1St == pt2St || pt1St == pt2Ed )
		{
			o_ptInter=pt1St;
			return 1;
		}
		//检查两条线是否首尾相接
		if(pt1Ed == pt2St || pt1Ed == pt2Ed )
		{
			o_ptInter=pt1Ed;
			return 1;
		}
		return -1;    //不相交
	}
		
	//定义交点的坐标并求得交点的坐标
	point InterSectPt;

	if((isInfinite1==0) && (isInfinite2==0)) //没有垂直线
	{
		InterSectPt.x = ((pt2St.y-pt1St.y)
					  - (Slope2*pt2St.x-Slope1*pt1St.x))
					  / (Slope1-Slope2);

		InterSectPt.y = pt1St.y+Slope1*(InterSectPt.x-pt1St.x);
		double ASertY   = pt2St.y+Slope2*(InterSectPt.x-pt2St.x);
	}
	//有一条是垂直线
	else if(isInfinite1==1 && isInfinite2==0) 
	{
		InterSectPt.x=pt1St.x;
		InterSectPt.y = pt2St.y+Slope2*(InterSectPt.x-pt2St.x);
	}
	//有一条是垂直线
	else if(isInfinite1==0 && isInfinite2==1) 
	{
		InterSectPt.x=pt2St.x;
		InterSectPt.y = pt1St.y+Slope1*(InterSectPt.x-pt1St.x);
	}
	else
		return 2;
	
	o_ptInter=InterSectPt;
	o_ptInter.z=(pt1St.z+pt2St.z)/2;

	//判断交点是否在pLine1和pLine2线上，如果都在则说明相交，否则不相交。
	if(PtInLine(pt1St,pt1Ed,o_ptInter)==1&&
		PtInLine(pt2St,pt2Ed,o_ptInter)==1)
		return 1;
	else if(PtInLine(pt1St,pt1Ed,o_ptInter)==1)
		return 3;
	else if(PtInLine(pt2St,pt2Ed,o_ptInter)==1)
		return 4;
	else
		return 0;
}

point Normalize(point pt)
{
	double dLength = GetLength(pt, point());
	if(dLength > ZERO)
	{
		return pt/dLength;
	}
	
	return pt;
}

double Modul(point pt)
{
	return GetLength(pt, point());
}

//将一个点从一个点移动到另一点移动一点(按极坐标)
//输入参数:point actPt,  要移动的点
//         const double dRadius,     移动方向上的步长（半径） 
//         const double dPolarAngle  移动方向的角度
void move(point &actPt, 
						   const double dRadius, 
						   const double dPolarAngle)
{
	actPt.x += dRadius*cos(dPolarAngle);
	actPt.y += dRadius*sin(dPolarAngle);
}


//将一个点从一个点移动到另一点移动一点(按直角坐标)
//输入参数:point actPt,  要移动的点
//         const point spt,    移动的起始点
//         const point ept     移动的终止点
void move(point& actPt, 
						   const point spt, 
						   const point ept)
{
	double OffsetX=ept.x-spt.x;
	double OffsetY=ept.y-spt.y;
	actPt.x += OffsetX;
	actPt.y += OffsetY;
}

void move(point pt, const double dRadius, const double dAngle, point &pt1)
{
	pt1 = pt;
	move(pt1, dRadius, dAngle);
}

void polar(point pt, const double dAngle, const double dRadius, point &pt1)
{
	pt1 = pt;
	move(pt1, dRadius, dAngle);
}

point polar(point pt, const double dAngle, const double dRadius)
{
	point pt1 = pt;
	move(pt1, dRadius, dAngle);
	return pt1;
}


point::GetDataToString(CString &s)
{	
	char ch[64];
	sprintf(ch, "%f,%f,%f", x, y, z);

	s = ch;
}

point::SetDataToString(CString s)
{
	array<CString> ars;
	StringSplite(s.GetBuffer(), ",", ars);
	int nSize = ars.getSize();

	x = y = z = 0.0;

	if(nSize > 0) x = atof(ars[0].GetBuffer());
	if(nSize > 1) y = atof(ars[1].GetBuffer());
	if(nSize > 2) z = atof(ars[2].GetBuffer());
}

X2S(CString &s, point pt)
{
	char ch[64];
	sprintf(ch, "%.10g,%.10g,%.10g", pt.x, pt.y, pt.z);

	s = ch;
}

typedef array<point> points;
X2S(CString &s, points& arpt)
{	
	CString sT = "";
	for(int i = 0; i < arpt.getSize(); i++)
	{		
		CString sTemp = "";
		X2S(sTemp, arpt[i]);
		
		char ch[64];
		if(i == 0)
			sprintf(ch, "%s", sTemp.GetBuffer());
		else
			sprintf(ch, ":%s", sTemp.GetBuffer());		
		sT += ch;				
	}
	s = sT;
}

S2X(CString s, points& arpt)
{	
	array<CString> ars;
	StringSplite(s.GetBuffer(), ":", ars);	
	for(int i = 0; i < ars.getSize(); i++)
	{		
		CString sTemp = ars[i];
		point pt(sTemp);
		arpt.add(pt);
	}
}

typedef point xyz;
CString X2S(point x) 
{
	CString s;
	X2S(s, x);
	return s;
}

CString X2S(points x)
{
	CString s;
	X2S(s, x);
	return s;
}


double GetDistance(point ptSt, point ptEd)
{
	return GetLength(ptSt, ptEd);
}

double max(double d0, double d1)
{
	if(d0 < d1)
		return d1;
	else
		return d0;
}

double min(double d0, double d1)
{
	if(d0 > d1)
		return d1;
	else
		return d0;
}

double min(double d0, double d1, double d2)
{
	double dt = min(d0, d1);
	return min(dt, d2);
}

double max(double d0, double d1, double d2)
{
	double dt = max(d0, d1);
	return max(dt, d2);
}

#define MIN min
#define MAX max

double GetAngle(point ptSt, point ptEd, int v_bStart = 1);
double GetAngle(point ptSt, point ptEd, int v_bStart)
{
	double Angle = 0.0;
	double OffsetX=ptEd.x-ptSt.x;
	double OffsetY=ptEd.y-ptSt.y;	
	if(fabs(OffsetX)<ZERO)
		OffsetX=0;
	if(fabs(OffsetY)<ZERO)
		OffsetY=0;
	
	if(OffsetX>0)
	{d
		if(OffsetY>=0)
			Angle=atan(OffsetY/OffsetX);
		else
			Angle=2*PI+atan(OffsetY/OffsetX);
	}
	else if(OffsetX<0)
	{
		Angle=PI+atan(OffsetY/OffsetX);
	}
	else
	{
		if(OffsetY>0)
			Angle=PI/2;
		else if(OffsetY<0)
			Angle=3*PI/2;
		else
			Angle=0;
	}
	//如果反向计算,则将角度加大180度,然后修正在0-360度之间
	if(v_bStart == 0)
	{
		Angle+=PI;
	}
	if(Angle>PI*2)
		Angle-=PI*2;
	else if(fabs(Angle-PI*2)<=ZERO)
		Angle=0;
	
	if(fabs(Angle-2*PI)<ZERO)
	{
		int i=0;
	}
	return Angle;
}

//弧度转角度
double rad2deg(double dAngle)
{
	return dAngle * 180.0 / PI;
}

//角度转弧度
double deg2rad(double dAngle)
{
	return dAngle * PI / 180.0;
}

double cosa(double dAngle)
{
	return cos(deg2rad(dAngle));
}

double cosha(double dAngle)
{
	return cosh(deg2rad(dAngle));
}

double sina(double dAngle)
{
	return sin(deg2rad(dAngle));
}

double sinha(double dAngle)
{
	return sinh(deg2rad(dAngle));
}

double tana(double dAngle)
{
	return tan(deg2rad(dAngle));
}

double tanha(double dAngle)
{
	return tanh(deg2rad(dAngle));
}

double atana(double d)
{
	return rad2deg(atan(d));
}

double atan2a(double d)
{
	return rad2deg(atan2(d));
}

double asina(double d)
{
	return rad2deg(asin(d));
}

double acosa(double d)
{
	return rad2deg(acos(d));
}

//求面积
double area(points &arpt)
{
	double dS = 0.0;
	for(int i = 0; i < arpt.getSize(); i++)
	{
		point pt1 = arpt[i];		
		point pt2;
		if(i >= arpt.getSize() - 1)
			pt2 = arpt[0];
		else
			pt2 = arpt[i + 1];
		
		dS += pt1.x * pt2.y - pt1.y * pt2.x;
	}
	
	dS *= 0.5;
	return dS;
}



