#include "stdafx.h"
#include "topologicalanalysis.h"


TopologicalAnalysis::TopologicalAnalysis(void)
{
}


TopologicalAnalysis::~TopologicalAnalysis(void)
{
}


bool TopologicalAnalysis::isPointInLine(double* point, double* startPoint, double* endPoint,float tolerance)
{
	double AX = startPoint[0];
	double AY = startPoint[1];
	double BX = endPoint[0];
	double BY = endPoint[1];
	double PX = point[0];
	double PY = point[1];

	double dx_AB = AX - BX;
	double dy_AB = AY - BY;
	double dx_PA = PX - AX;
	double dy_PA = PY - AY;
	double dx_PB = PX - BX;
	double dy_PB = PY - BY;

	double AB = sqrt(dx_AB*dx_AB + dy_AB*dy_AB);
	double PA = sqrt(dx_PA*dx_PA + dy_PA*dy_PA);
	double PB = sqrt(dx_PB*dx_PB + dy_PB*dy_PB);
	double rate = abs(PA + PB - AB) / AB;
	if (rate < tolerance)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//ÅжÏÏßÊÇ·ñÔÚÕÛÏßÉÏ
int TopologicalAnalysis::isPointInPolyLine(double* point, vector<double>& lineX,vector<double>& lineY,float tolerance)
{
	int lineNum = lineX.size();
	double startPoint[2],endPoint[2];
	for (int i=0;i<lineNum-1;i++)
	{
		startPoint[0] = lineX.at(i);
		startPoint[1] = lineY.at(i);
		endPoint[0] = lineX.at(i+1);
		endPoint[1] = lineY.at(i+1);
		bool b_in = isPointInLine(point,startPoint,endPoint,tolerance);
		if(b_in)
		{
			return (i+1);
		}
	}
	//ÅжÏÊÕβµãÏß¶Î
	startPoint[0] = lineX.at(lineNum-1);
	startPoint[1] = lineY.at(lineNum-1);
	endPoint[0] = lineX.at(0);
	endPoint[1] = lineY.at(0);
	bool b_end = isPointInLine(point,startPoint,endPoint,tolerance);
	if (b_end)
	{
		return lineNum;
	}
	else
	{
		return 0;
	}
}

//¸ù¾ÝÁ½µãÇó³ö´¹Ïß¹ýµÚÈýµãµÄÖ±ÏߵĽ»µã
bool TopologicalAnalysis::GetPointToLineVerticalCross(double* linePt1,double* linePt2,double* pt,double* crossPt)
{
	//´¹Ö±Ïß
	if (linePt1[0] == linePt2[0])
	{
		crossPt[0] = linePt1[0];
		crossPt[1] = pt[1];
		return true;
	}
	//ˮƽÏß
	if (linePt1[1] == linePt2[1])
	{
		crossPt[0] = pt[0];
		crossPt[1] = linePt1[1];
		return true;
	}
	float A = (linePt1[1]- linePt2[1]) * 1.0 / (linePt1[0]- linePt2[0]);
	float B = (linePt1[1] - A * linePt1[0]);
	float m = pt[0] + A * pt[1];

	/// ÇóÁ½Ö±Ïß½»µã×ø±ê
	crossPt[0] = (m - A * B) * 1.0f / (A * A + 1);
	crossPt[1] = A * crossPt[0] + B;
	return true;
}

//ÅжϵãÊÇ·ñÔÚ(¼òµ¥)¶à±ßÐÎÄÚ
//polygon: Ê×βÏàͬµÄCpoint1Áбí
bool TopologicalAnalysis::isPointInPolygon(CPoint1 point, vector<CPoint1> polygon){
	if (polygon.size()<=3) return false;	// Ò»¸öÓÐЧ¶à±ßÐζ¥µãÊýÓ¦´óÓÚ3

	int LineNum = polygon.size();
	CPoint1 leftP = point;
	CPoint1 rightP;
	rightP.SetX(getMaxX(polygon) + 1);
	rightP.SetY(point.GetY());
	int count = 0, yPrev = polygon[LineNum - 2].GetY();
	CPoint1 v1, v2;
	v1 = polygon[LineNum - 1];
	for (int i = 0; i < LineNum; i++)
	{
		v2 = polygon[i];

		if (isPointInLine(leftP, v1, v2))
			return true;

		if (v1.GetY() != v2.GetY())
		{
			if (isLineIntersect(v1, v2, leftP, rightP))
			{
				if (isPointInLine(v1, leftP, rightP))
				{
					if (v1.GetY()<v2.GetY()) { if (v1.GetY()>yPrev)  count++; }
					else { if (v1.GetY() < yPrev) count++; }
				}
				else if (!isPointInLine(v2, leftP, rightP))
				{
					count++;
				}
			}
		}
		yPrev = v1.GetY();

		v1 = v2;
	}
	return   (count % 2 == 1);
}

double TopologicalAnalysis::getMaxX(vector<CPoint1> points){
	if (points.size()==0)
		return -1;
	else if(points.size()==1)
		return points[0].GetX();
	else{
		double maxx = points[0].GetX();
		for (unsigned i=1; i<points.size();i++)
		{
			if(points[i].GetX()>maxx){
				maxx = points[i].GetX();
			}
		}
		return maxx;
	}
}

bool  TopologicalAnalysis::isPointInLine(CPoint1 point, CPoint1 startPoint, CPoint1 endPoint)
{
	long AX = startPoint.GetX();
	long AY = startPoint.GetY();
	long BX = endPoint.GetX();
	long BY = endPoint.GetY();
	long PX = point.GetX();
	long PY = point.GetY();

	double dx_AB = AX - BX;
	double dy_AB = AY - BY;
	double dx_PA = PX - AX;
	double dy_PA = PY - AY;
	double dx_PB = PX - BX;
	double dy_PB = PY - BY;

	double AB = sqrt(dx_AB*dx_AB + dy_AB*dy_AB);
	double PA = sqrt(dx_PA*dx_PA + dy_PA*dy_PA);
	double PB = sqrt(dx_PB*dx_PB + dy_PB*dy_PB);
	double rate = abs(PA + PB - AB) / AB;
	if (rate < 0.001)
	{
		return true;
	}
	else
	{
		return false;
	}
}
// ²æ»ý
double mult(CPoint1 a, CPoint1 b, CPoint1 c)  
{  
	return (a.GetX()-c.GetX())*(b.GetY()-c.GetY())-(b.GetX()-c.GetX())*(a.GetY()-c.GetY());  
}

bool TopologicalAnalysis::isLineIntersect(CPoint1 line1Start, CPoint1 line1End, CPoint1 line2Start, CPoint1 line2End){
	double l1sx = line1Start.GetX();
	double l1sy = line1Start.GetY();
	double l1ex = line1End.GetX();
	double l1ey = line1End.GetY();
	double l2sx = line2Start.GetX();
	double l2sy = line2Start.GetY();
	double l2ex = line2End.GetX(); 
	double l2ey = line2End.GetY();
	if ( max(l1sx, l1ex)<min(l2sx, l2ex) )  
	{  
		return false;  
	}  
	if ( max(l1sy, l1ey)<min(l2sy,l2ey) )  
	{  
		return false;  
	}  
	if ( max(l2sx, l2ex)<min(l1sx, l1ex) )  
	{  
		return false;  
	}  
	if ( max(l2sy,l2ey)<min(l1sy, l1ey) )  
	{  
		return false;  
	}  
	if ( mult(line2Start, line1End, line1Start)*mult(line1End, line2End, line1Start)<0 )  
	{  
		return false;  
	}  
	if ( mult(line1Start, line2End, line2Start)*mult(line2End, line1End, line2Start)<0 )  
	{  
		return false;  
	}  
	return true;  
}