/*
 * @author jarmo Suoranta
 */


var WGS_COORDS = 5;
var KKJ_COORDS = 3;


/* 
 *  Coverts coodinates of the KKJ carthesian system to the WGS84 coordinates system (also in carthesian format).  
 *  Returns an array that includes these WGS84 coordinates. Firts in the array (index[0]) is x -coordinate (north) 
 *  and second (index[1]) is Y -coordinate (East).
 *
 *   
 */


function KKJToWGS(x,y){
	var Long0 = 27.0;
    Long0 = deg2rad(Long0);
    

    var MinLa = deg2rad(59.0);
    var MaxLa = deg2rad(70.5);
    var MinLo = deg2rad(18.5);
    var MaxLo = deg2rad(32.0);

    
    var lalo_la = 0;
	var lalo_lo = 0;

    for (var i = 1; i < 35; i++) {

      var DeltaLa = MaxLa - MinLa;
      var DeltaLo = MaxLo - MinLo;

      lalo_la = (MinLa + 0.5 * DeltaLa);
      lalo_lo = (MinLo + 0.5 * DeltaLo);
	

      var coords = KKJLaLo_to_KKJxy(lalo_la, lalo_lo, Long0);
	  var tempY = coords[1];
	  var tempX = coords[0];		
	 
      if (tempY < y) {
        MinLa = (MinLa + 0.45 * DeltaLa);
      }
      else {
        MaxLa = (MinLa + 0.55 * DeltaLa);
      }

      if (tempX < x) {
        MinLo = (MinLo + 0.45 * DeltaLo);
      }
      else {
        MaxLo = (MinLo + 0.55 * DeltaLo);
      }

    }	

    var La = rad2deg(lalo_la);
    var Lo = rad2deg(lalo_lo);


    var dLa = deg2rad(0.124867E+01 +
                                -0.269982E+00 * La +
                                0.191330E+00 * Lo +
                                0.356119E-02 * La * La +
                                -0.122312E-02 * La * Lo +
                                -0.335514E-03 * Lo * Lo) / 3600.0;
    var dLo = deg2rad( -0.286111E+02 +
                                0.114183E+01 * La +
                                -0.581428E+00 * Lo +
                                -0.152421E-01 * La * La +
                                0.118177E-01 * La * Lo +
                                0.826646E-03 * Lo * Lo) / 3600.0;

    lalo_la = lalo_la + dLa;
    lalo_lo = lalo_lo + dLo;

    var degY = rad2deg(lalo_la) + 0.0000000001;
    degY = Math.round(degY*Math.pow(10,WGS_COORDS))/Math.pow(10,WGS_COORDS);    
    
    var degX = rad2deg(lalo_lo) + 0.0000000001;
    degX = Math.round(degX*Math.pow(10,WGS_COORDS))/Math.pow(10,WGS_COORDS);
	    
    return new Array(degX,degY);   

} 


function WGSToKKJ(x,y) {

    var latitude = this.deg2rad(y);
    var longitude = this.deg2rad(x);

    var la = this.rad2deg(latitude);
    var lo = this.rad2deg(longitude);
	

    var dLa = this.deg2rad( -0.124766E+01 +
                                0.269941E+00 * la +
                                -0.191342E+00 * lo +
                                -0.356086E-02 * la * la +
                                0.122353E-02 * la * lo +
                                0.335456E-03 * lo * lo) / 3600.0;
    var dLo = this.deg2rad(0.286008E+02 +
                                -0.114139E+01 * la +
                                0.581329E+00 * lo +
                                0.152376E-01 * la * la +
                                -0.118166E-01 * la * lo +
                                -0.826201E-03 * lo * lo) / 3600.0;
    var lat = latitude + dLa;
    var lon = longitude + dLo;

    // *********************************************

    var long0 = this.deg2rad(3 * 3.0 + 18.0);

    // *********************************************
	
	 var coords = KKJLaLo_to_KKJxy(lat, lon, long0);
	 
	 var tempY = Math.round(coords[1]*Math.pow(10,KKJ_COORDS))/Math.pow(10,KKJ_COORDS);  ;
	 var tempX = Math.round(coords[0]*Math.pow(10,KKJ_COORDS))/Math.pow(10,KKJ_COORDS);  ;
	 
	 return new Array(tempX,tempY);    

  } 


/*
 * 
 * Converse KKJ geodetic (polar) coordinates to the KKJ cartesian (rectangular) coordinate system. 
 * Returns an array that includes points x (north) and y (east) coordinates. 
 * First in the array is x (index[0]) and second is y (index[1]).  
 */
function KKJLaLo_to_KKJxy(lat, lon,long0){
	var ZoneNumber = 3;

    var lo = lon - long0;	


    var a = 6378388.0; // Hayford ellipsoid
    var f = 1 / 297.0; // flaten ration of the ellipsoid



    var b = (1.0 - f) * a;
    var bb = b * b; // b
    var c = (a / b) * a; // c   = a/b
    var ee = (a * a - bb) / bb; // e' = (a - b)/b
    var n = (a - b) / (a + b); // n   = (a-b)/(a+b)
    var nn = n * n; // n

    var cosLa = Math.cos(lat);
	

    var NN = ee * cosLa * cosLa; // Eta = e' cos Latitude    

    var LaF = Math.atan(Math.tan(lat) / Math.cos(lo * Math.sqrt(1 + NN)));

    var cosLaF = Math.cos(LaF);

    var t = (Math.tan(lo) * cosLaF) / Math.sqrt(1 + ee * cosLaF * cosLaF);

    var A = a / (1 + n);

    var A1 = A * (1 + nn / 4 + nn * nn / 64);

    var A2 = A * 1.5 * n * (1 - nn / 8);

    var A3 = A * 0.9375 * nn * (1 - nn / 4);

    var A4 = A * 35 / 48.0 * nn * n;



    var tempY = A1 * LaF -
        A2 * Math.sin(2 * LaF) +
        A3 * Math.sin(4 * LaF) -
        A4 * Math.sin(6 * LaF);
    var tempX = c * Math.log(t + Math.sqrt(1 + t * t)) +
        500000.0 + ZoneNumber * 1000000.0;



	var coords = new Array(tempX,tempY);
	return coords;
}

/*  Coverse degrees to radians
 * 
 */

function deg2rad(degrees){
	var rads = degrees * ((2 * Math.PI) / 360);
	return rads;
}
/*  Coverse radians to degrees
 * 
 */
function rad2deg(rads){
	var degs = rads * (180/Math.PI);
	return degs;
	
}



  
function worldmercator2wgs84 (x,y) {
	
  	var r = 6378137.0;
  	  	
	var lon =  rad2deg(x/r);
	
	var f = 1/298.257223563;

	var e = Math.sqrt(2*f-Math.pow(f,2));
	
	var t = Math.pow(Math.E,(-1.0 * y) / r);
	
	var lat = Math.PI/2-2*Math.atan(t);
	
	for(var i = 0; i < 10; i++){
		var temp = lat;		
		lat = (Math.PI / 2) - 
			(2 * Math.atan(t * Math.pow((1-e*Math.sin(temp))/(1+e*Math.sin(temp)),(e/2))));
		//console.info(temp-lat);
		}
	

 	var lat = rad2deg(lat);

	
    return new Array({'lon':lon,'lat':lat});
  


  
  }
 

function wgs842worldmercator(lon,lat) {
	
  	var a = 6378137;	

  	var f = (1/298.257223563);
  	var e = Math.sqrt(2*f-Math.pow(f,2));
  	
 	var lat = deg2rad(lat);
 	var lon = deg2rad(lon);
 	
 	var esin = e*Math.sin(lat); 	
 	
 	var x = a*lon;

  	var y = a*Math.log( Math.tan(Math.PI/4 + lat/2) * Math.pow( ((1 - esin) / (1 + esin)),(e/2)));
	
    return new Array({'x':x,'y':y});
    
    
  }

function sinh(x)
{
	
	return (Math.exp(x) - Math.exp(-x))/2;
}

function asinh(x)
{
	
	return Math.log(x + Math.sqrt(1 + x * x));
}
