//
// Created by LGW on 2017/5/11.
//
#pragma once

#include <math.h>
#include <string>
#define M_PI 3.14159265358979323846
#define DEFFAULT_LONTITUDE -9999
using namespace std;


namespace coord {
	/**
	*  ṹ
	*/
	struct Point  //ṹ
	{
		double x;
		double y;
		double z;
		Point() {}
		Point(double _x, double _y, double _z) :x(_x), y(_y), z(_z){}
	};

	/**
	* 
	*/
	struct EllipsoidParam
	{
		string name;
		double a;
		double b;
		double f;
	};

	/**
	* ϵö
	*/
	enum GEODETIC_COORD_SYSTEM
	{
		XIAN80,
		WGS84
	};

	/**
	*  ϵƣa,b,f
	*/
	static EllipsoidParam EllipsoidParamArray[] =
	{
		{ "XIAN80", 6378140, 6356755.2882, 1 / 298.257 },
		{ "WGS84", 6378137, 6356752.314, 1 / 298.2572236 }
	};
}

using namespace coord;
class Trans
{
private:
	double
		dx,//xƽ()
		dy,//yƽ()
		dz,//zƽ()
		Ox,//xתǶ()
		Oy,//yתǶ()
		Oz,//zתǶ()
		k; //߶(ppm)ʵӦñmʾ
	//Ҫ˵һ£߶ֵλıʾʽһֽԼΪ11.0000045kʾ
	//һ־ppmıʾʽ΢1һ㣬4.5mʾk=1+m/1000000
	
	GEODETIC_COORD_SYSTEM coordSystem_origin;//ԭʼϵ
	GEODETIC_COORD_SYSTEM coordSystem_result;//ϵ
	
private:
	/**
	 * ǶתΪ
	 */
	double toRadians(double angdeg);

	/**
	 * תΪǶ
	 */
	double toDegrees(double angdeg);


public:
	/**
	 * ߲ + ԭʼϵ + ϵ
	 */
	Trans(double dx, double dy, double dz, double Ox, double Oy, double Oz, double k,
		GEODETIC_COORD_SYSTEM _coordSystem_origin, GEODETIC_COORD_SYSTEM _coordSystem_result);

	~Trans();

	GEODETIC_COORD_SYSTEM getOriginCoordSystem()
	{
		return coordSystem_origin;
	}

	GEODETIC_COORD_SYSTEM getResultCoordSystem()
	{
		return coordSystem_result;
	}

	/**
	 * תռ
	 * 룺pt:(ȡ)  ab:ôϵĳ̰(m)
	 * ռ(m)
	 */
	Point geodetic2spatial(Point pt,double a ,double b);
	
	/**
	 * ߲㣨spatial1 -> spatial2
	 * 룺point:ռ(m) 
	 * ռ(m)
	 */
	Point qicanshu(Point point);

	/**
	* ռת
	* 룺pt:ռ(m)  af:ϵĳ(m)ͱ
	* (ȡ)
	*/
	Point spatial2geodetic(Point pt, double a, double f);

	/**
	 * ˹ͶӰ ->ƽ
	 * Lo; //뾭() ˹ͶӰʱʹ ṩĻ뾭߼㣬ûṩͨó
	 * abf:ϵĳ̰(m)ͱ
	 * ZoneWide: 3 or 6
	 */
	Point gaussPrj_geodetic2plane(Point point, double a, double b, double f, int ZoneWide, int Lo = DEFFAULT_LONTITUDE);

	/**
	 * ˹ ƽ->
	 * Lo; //뾭() ˹ͶӰʱʹ ṩĻ뾭߼㣬ûṩͨó 
	 * ab:ϵĳ̰(m)
	 * ZoneWide: 3 or 6
	 */
	Point gaussInversePrj_plane2geodetic(Point point, double a, double b,int ZoneWide, int Lo = DEFFAULT_LONTITUDE);

	/**
	 * ϵ1µľγ -> ϵ2µĸ˹ͶӰƽ
	 * 룺pointϵ1µľγ꣩,*_originֱΪϵ1Ӧĳ̰ᣨm
	 * 룺*_resultֱΪϵ2Ӧĳ̰ᣨmʣZoneWide: 3 or 6Lo; //뾭() ˹ͶӰʱʹãѡ
	 * ϵ2µĸ˹ͶӰƽ
	 */
	Point geodetic2plane(Point point, double a_origin, double b_origin, double a_result, double b_result, double f_result, int ZoneWide, int Lo = DEFFAULT_LONTITUDE);

	/**
	* ϵ1µĸ˹ͶӰƽ -> ϵ2µľγ
	* 룺pointϵ1µĸ˹ͶӰƽ꣩,*_originֱΪϵ1Ӧĳ̰ᣨm
	* 룺*_resultֱΪϵ2Ӧĳ̰ᣨmʣZoneWide: 3 or 6Lo; //뾭() ˹ͶӰʱʹãѡ
	* ϵ2µľγ
	*/
	Point plane2geodetic(Point point, double a_origin, double b_origin, double f_origin, double a_result, double f_result, int ZoneWide, int Lo = DEFFAULT_LONTITUDE);

	/**
	 * ϵ1µľγ -> ϵ2µĸ˹ͶӰƽ
	 * 룺ZoneWide: 3 or 6Lo; //뾭() ˹ͶӰʱʹãѡ
	 * ʹù캯öͶӦĲ
	 */
	Point geodetic2plane(Point point, int ZoneWide, int Lo = DEFFAULT_LONTITUDE);

	/**
	 * ϵ1µĸ˹ͶӰƽ -> ϵ2µľγ
	 * 룺ZoneWide: 3 or 6Lo; //뾭() ˹ͶӰʱʹãѡ
	 * ʹù캯öͶӦĲ
	 */
	Point plane2geodetic(Point point, int ZoneWide, int Lo = DEFFAULT_LONTITUDE);
};

