function ALG0004(X,Y,n,c,Xs,Ys,lambdac,e,epsilon)
{
	var R = Math.sqrt( Math.pow((X - Xs),2) + Math.pow((Y - Ys),2) );
	var gamma = Math.atan((X - Xs)/(Ys - Y));
	var lambda = lambdac + (gamma / n);
	var L = (-1 / n) * Math.log(Math.abs(R/c));
	var phi = ALG0002(L,e,epsilon);
	
	var coords = [];	
	coords['lambda']=lambda;
	coords['phi']=phi;
	
	return coords;
}

function ALG0002(L,e,epsilon)
{
	var phi = [];
	phi[0] = 2 * Math.atan(Math.exp(L)) - (Math.PI/2);
	
	var i = 0;
	do
	{
		i++;
		var temp = (1 + (e * Math.sin(phi[i-1]))) / (1 - (e * Math.sin(phi[i-1])));
		phi[i] = 2 * Math.atan(Math.pow(temp, (e/2)) * Math.exp(L)) - Math.PI/2;
	}
	while (Math.abs(phi[i] - phi[i - 1]) >= epsilon);
	
	return phi[i];
}

function ALG0009(lambda,phi,he,a,e)
{
	var N = ALG0021(phi,a,e);
	var X = (N + he) * Math.cos(phi) * Math.cos(lambda);
	var Y = (N + he) * Math.cos(phi) * Math.sin(lambda);
	var Z = (N * (1 - e*e)  + he) * Math.sin(phi);
	
	var coords = [];
	coords['X']=X;
	coords['Y']=Y;
	coords['Z']=Z;
	
	return coords;
}

function ALG0013(Tx,Ty,Tz,D,Rx,Ry,Rz,U)
{
	var V = [];
	
	V['X'] = Tx + U['X'] * (1 + D) + U['Z'] * Ry - U['Y'] * Rz;
	V['Y'] = Ty + U['Y'] * (1 + D) + U['X'] * Rz - U['Z'] * Rx;
	V['Z'] = Tz + U['Z'] * (1 + D) + U['Y'] * Rx - U['X'] * Ry;

	return V;
}

function ALG0021(phi,a,e)
{
	var N = a/Math.sqrt( 1 - e * e * Math.sin(phi) * Math.sin(phi) );
	
	return N;
}

function ALG0012(X,Y,Z,a,e,epsilon)
{
	var lambda = Math.atan (Y/X);
	var P = Math.sqrt(X*X + Y*Y);
	var phi = [];
	phi[0] = Math.atan(Z/ (P * (1 - ( (a*e*e)/Math.sqrt(X*X + Y*Y + Z*Z) ) ) ) );
	var i = 0;
	do
	{
		i++;
		var temp =  Math.pow((1 - ( a * e*e * Math.cos(phi[i - 1] )/( P * Math.sqrt(1 - e*e * Math.sin(phi[i - 1])*Math.sin(phi[i - 1]))))),-1);
		phi[i] = Math.atan(temp * Z / P );
	}
	while (Math.abs(phi[i] - phi[i - 1]) >= epsilon);
	
	var phix = [];
	phix = phi[i];
	var he = (P/Math.cos(phix)) - (a/Math.sqrt(1 - e*e * Math.sin(phix)*Math.sin(phix)));
	
	var coords = [];
	coords['lambda']=lambda;
	coords['phi']=phix;
	coords['he']=he;
	
	return coords;
}

function rad2deg(angle)
{
	return (angle/Math.PI) * 180;
}

function Lambert2LatLong(X,Y)
{
	var epsilon = 0.00000000001;


	var n = 0.7289686274;
	var c = 11745793.39;
	var Xs = 600000;
	var Ys = 8199695.768;
	var lambdac = 0.04079234433; // pour greenwich

	var e = 0.08248325676; //(première excentricité de l’ellipsoïde Clarke 1880 français)

	var he = 100;
	var a = 6378249.2;

	var Tx = -168;
	var Ty = -60;
	var Tz = +320;
	var D  = 0;
	var Rx = Ry = Rz = 0;

	var coords = [];
	coords = ALG0004(X,Y,n,c,Xs,Ys,lambdac,e,epsilon);
	coords = ALG0009(coords['lambda'],coords['phi'],he,a,e);
	coords = ALG0013(Tx,Ty,Tz,D,Rx,Ry,Rz,coords);
	
	a = 6378137.0;    // ellipsoïdes WGS84
	var f = 1/298.257223563;
	var b = a*(1-f);
	e = Math.sqrt((a*a - b*b)/(a*a));

	X = coords['X'];
	Y = coords['Y'];
	var Z = coords['Z'];
	
	coords = ALG0012(X,Y,Z,a,e,epsilon);
	
	coords[1] = rad2deg(coords['lambda']);
	coords[0] = rad2deg(coords['phi']);
		
	return coords;
}

function LatLong2lambertII(X,Y)
{
	//0)degres-minutes-secondes + orientation (d,m,s,o) en radian
	var lambda_w = X * Math.PI/180 ;
	var phi_w =  Y * Math.PI/180 ;

	//1) coordonnées géographiques WGS84 (phi_w,lambda_w) en coordonnées cartésiennes WGS84 (X_w,Y_w,Z_w)
	var a_w = 6378137.0;
	var b_w = 6356752.314;
	var e2_w = (a_w*a_w-b_w*b_w)/(a_w*a_w);

	//et on a la grande normale de l'ellipsoide WGS84
	var N = a_w/Math.sqrt(1-e2_w*Math.pow(Math.sin(phi_w),2));

	//ainsi on obtient
	var X_w = N * Math.cos(phi_w) * Math.cos(lambda_w);
	var Y_w = N * Math.cos(phi_w) * Math.sin(lambda_w);
	var Z_w = N * (1-e2_w) * Math.sin(phi_w);

	//2) coordonnées cartésiennes WGS84 (X_w,Y_w,Z_w) en coordonnées cartésiennes NTF (X_n,Y_n,Z_n)
	var dX = 168.0;
	var dY = 60.0;
	var dZ = -320.0;
	var X_n = X_w + dX;
	var Y_n = Y_w + dY;
	var Z_n = Z_w + dZ;

	//3) coordonnées cartésiennes NTF (X_n,Y_n,Z_n) en coordonnées géographiques NTF (phi_n,lambda_n)
	var a_n = 6378249.2;
	var b_n = 6356515.0;
	var e2_n = (a_n*a_n-b_n*b_n)/(a_n*a_n);

	//on définit une tolérance de convergence
	var epsilon = Math.pow(10,-10);

	//puis on amorce une boucle de calcul        
	var p0 = Math.atan(Z_n/Math.sqrt(X_n*X_n+Y_n*Y_n)*(1-(a_n*e2_n)/(Math.sqrt(X_n*X_n+Y_n*Y_n+Z_n*Z_n))));

	var p1 = Math.atan((Z_n/Math.sqrt(X_n*X_n+Y_n*Y_n))/(1-(a_n*e2_n*Math.cos(p0))/(Math.sqrt((X_n*X_n+Y_n*Y_n)*(1-e2_n*Math.pow(Math.sin(p0),2))))));

	while(!(Math.abs(p1-p0)<epsilon)){
		p0 = p1;
		p1 = Math.atan((Z_n/Math.sqrt(X_n*X_n+Y_n*Y_n))/(1-(a_n*e2_n*Math.cos(p0))/(Math.sqrt((X_n*X_n+Y_n*Y_n)*(1-e2_n*Math.pow(Math.sin(p0),2))))));
	}

	var phi_n = p1;
	var lambda_n = Math.atan(Y_n/X_n);

	//4) coordonnées géographiques NTF (phi_n,lambda_n) en coordonnées projetées en Lambert II étendu (X_l2e, Y_l2e)
	var n = 0.7289686274;
	var c = 11745793.39;
	var Xs = 600000.0;
	var Ys = 8199695.768;

	var e_n = Math.sqrt(e2_n);
	var lambda0 = 0.04079234433198;   //correspond à la longitude en radian de Paris (2°20'14.025" E) par rapport à Greenwich

	//puis on calcule la latitude isométrique
	var L = Math.log(Math.tan(Math.PI/4 + phi_n/2) * Math.pow(((1-e_n*Math.sin(phi_n))/(1+e_n*Math.sin(phi_n))),(e_n/2)));

	//enfin on projette
	var X_l2e = Xs + c*Math.exp((-n*L))*Math.sin(n*(lambda_n-lambda0));
	var Y_l2e = Ys - c*Math.exp((-n*L))*Math.cos(n*(lambda_n-lambda0));

	X_l2e = Math.round(X_l2e,2);
	Y_l2e = Math.round(Y_l2e,2);
	
	var tab = [];
	tab[0] = X_l2e;
	tab[1] = Y_l2e;

	return tab;
}


