
#ifndef _CARD_PATH_HPP_
#define _CARD_PATH_HPP_
#include "point.h"
NAMESPACE_POINT_BEGIN (NAMESPACE_POINT)

struct line:point
{
	point  pt;
	double a,b,c;
	double cos;
	double sin;
	double length;
	int    direct;
	line()
	{
		reset();
	}

	std::string to_string()const
	{
		char buf[256];
		int len=sprintf(buf,"[(%.3f,%.3f),(%.3f,%.3f),%.3f]",x,y,pt.x,pt.y,cos);

		return std::string(buf,len);
	}

	bool empty()const
	{
		return cos+sin==0;
	}

	line& reset()
	{
		memset(this,0,sizeof(*this));
		return *this;
	}

	void set_next(const point&pt)
	{
		set_next(pt.x,pt.y);
	}

	void set_next(double x,double y)
	{
		if(dist(x,y)<1)
			return;

		pt.set(x,y);

		auto abc=get_abc(pt);

		a=std::get<0>(abc);
		b=std::get<1>(abc);
		c=std::get<2>(abc);

		cos=cos_k(pt);
		sin=sin_k(pt);

		length=dist(pt);
	}

	bool test(const point&p)const
	{
		return test(p.x,p.y);
	}

	bool test(double x,double y)const
	{
		return fabs(a*x+b*y+c)<1;
	}

	int push(const point&pt)
	{
		return push(pt.x,pt.y);
	}

	int push(double x,double y)
	{
		if(!empty())
		{
			if(test(x,y))
			{
				pt.set(x,y);
				return 0;
			}

			return -1;
		}

		set_next(x,y);
		return 1;
	}

	point  map(double length)
	{
		return point(x+length*cos,y+length*sin);
	}
};

struct vec
{
	


};

struct path
{
	
	


};

//所有的顶点
struct vertexs
{
	std::vector<point> v;
};

//整个地图的路径信息
struct map_path
{
	

	



};

//一维、二维坐标进行转换的工具类
//使用this->add_point按照路径顺序加入途径点
//使用this->map进行一维、二维坐标之间的相互转换
struct card_path
{
	private:
		const site*		last_site;
		zlist<line,64> &path;
		card_path(const card_path&);

	private:
		static inline bool eq(double x1,double x2)
		{
			return fabs(x1-x2)<0.1; //小于10厘米的误差认为是一个点
		}

	public:
		/*
			输入起始点，返回途经点
		*/
		int find_path(const point&from,const point&to,std::array<point,8>&ret)
		{
		
		
			return 0;
		}


		/*
		   输入路径上的二维点(x,y)，输出该点的一维坐标
		   return -1. : (x,y) 不在路径上或者当前对象不包含合法路径
		   return >=0 : (x,y) 一维坐标
		*/
		double map(double x,double y)const
		{
			double rc=0.;
			for(int i=0,len=path.size();i<len;i++)
			{
				const line&p=path[i];
				if(p.test(x,y))
				{
					return rc+p.dist(x,y);
				}

				rc+=p.length;
			}

			assert(false);
			return -1.;
		}

		double  map(const point&p)const
		{
			return map(p.x, p.y);
		}

		/*
		   输入一维坐标(dist),转换为二维坐标输出(point)
		   如果给定一维坐标超出当前路径长度，返回 point::invalid_point() 
		 */
		point  map(double length)
		{
			if(empty())
				return point();

			for(int i=0,len=path.size()-1;i<len;i++)
			{
				line&v=path[i];
				if(length<=v.length)
					return v.map(length);

				length-=v.length;
			}

			return path(0).map(length);
		}

	public:
		card_path()
			:last_site(nullptr)
			,path(*new zlist<line,64>())
		{
		}
	
		~card_path()
		{
			delete &path;
		}

		bool empty() const
		{
			return path.empty() || path[0].empty();
		}

		std::string to_string()const
		{
			std::string rc;
			for(int i=0,len=path.size();i<len;i++)
			{
				rc+=path[i].to_string();
				rc+=", ";
			}

			return std::move(rc);
		}

		void log()const
		{
			printf("path-point:%s\n",to_string().c_str());
		}

		int test(const point&p,int start=0)
		{
			for(int i=start,len=path.size();i<len;i++)
			{
				if(path[i].test(p))
					return i;
			}

			return -1;
		}

		void enter_site(const site*sit)
		{
			if(last_site==nullptr)
				last_site=sit;

			if(last_site==sit||empty())
				return;

			point pt=last_site->intersection(*sit);

			last_site=sit;

			if(pt.empty()||pt.dist(last_point)>25)
				return;

			path(0).set_next(pt.x,pt.y);
			path.grow().reset().set(pt);
		}

		//加入路径坐标
		bool add(const point&pt)
		{
			if(pt.empty())
				return false;

			if(pt.dist(last_point)<1)
				return false;

			last_point=pt;
			if(path.empty()) 
			{
				path.grow().reset().set(pt);
				return true;
			}

			int rc=path(0).push(pt);

			if(rc==0)
				return true;

			if(rc<0)
			{
				path.grow().reset().set(pt);
			}

			return true;
		}

		void set_header(const point&p)
		{
			if(p.empty())
				return;
			int i=test(p);
			if(i>=0) 
			{
				path.skip(i);

				path[0].set(p);
				if(!path[0].pt.empty())
					path[0].set_next(path[0].pt);
			}
		}


		/*
		   输入路径上的二维点(x,y)，输出该点的一维坐标
		   return -1. : (x,y) 不在路径上或者当前对象不包含合法路径
		   return >=0 : (x,y) 一维坐标
		*/
		double map(double x,double y)const
		{
			double rc=0.;
			for(int i=0,len=path.size();i<len;i++)
			{
				const line&p=path[i];
				if(p.test(x,y))
				{
					return rc+p.dist(x,y);
				}

				rc+=p.length;
			}

			assert(false);
			return -1.;
		}

		double  map(const point&p)const
		{
			return map(p.x, p.y);
		}
		/*
		   输入一维坐标(dist),转换为二维坐标输出(point)
		   如果给定一维坐标超出当前路径长度，返回 point::invalid_point() 
		 */
		point  map(double length)
		{
			if(empty())
				return point();

			for(int i=0,len=path.size()-1;i<len;i++)
			{
				line&v=path[i];
				if(length<=v.length)
					return v.map(length);

				length-=v.length;
			}

			return path(0).map(length);
		}
};

NAMESPACE_POINT_END(NAMESPACE_POINT)
#endif

