// CH1903 <=> WGS84 Approx
//
// Implementation of the approximative conversion function 
// of the federal swiss topological institute.
// (c) nico waldispuehl 08
//
// Results are sufficiently precise on the area of switzerland. 
//



 /*
  * Double toSexagesimalSec(Double x)
  *
  * Transforms a value from degrees to sexagesimalsecs.
  * Takes a double value as input and returns a double value.
  *
  * Is used as a helper function for the conversion functions
  */
  
  function toSexagesimalSec(x)
  {	
  	var deg = Math.floor(x);
  	var min = Math.floor((x - deg) * 60);
  	
  	// Note that we don't floor or round the value of seconds
  	// to keep the current precision
  	var sec = (x - deg - (min/60)) * 3600;

  	return (deg * 3600) + (min * 60) + sec;	
  }

 /*
  * Array(Double, Double) swissGridToCoords(Integer y, Integer x)
  *
  * Transforms a coordinate from the swiss grid system to
  * actual world coordinates in longitude and latitude.
  *
  * Takes two integers as input. Returns an array of doubles.
  *
  * Note that the names of the input arguments are misleading 
  * because of a inconsistency of the swiss grid with a common
  * coordinate system; y is the longitudial part (from right) and
  * x is the latitudial part (from bottom).
  *
  * Use the usual form to input the data; to convert a swiss grid
  * coordinate of let's say 600000/200000 use the function as follows:
  *
  * var result = swissGridToCoords(600000, 200000);
  *
  * result contains now: 46.951081, 7.438637
  */
  
  function swissGridToCoords(y,x)
  {
    // Calculate some helper values
  	var y_prime = (y - 600000) / 1000000; 
  	var x_prime = (x - 200000) / 1000000;
  	
  	var lng = 2.6779094 +
  		  4.728982 * y_prime +
  		  0.791484 * y_prime * x_prime +
  		  0.1306 * y_prime * Math.pow(x_prime, 2) -
  		  0.0436 * Math.pow(y_prime, 3);

  	var lat = 16.9023892 +
  		  3.238272 * x_prime -
  		  0.270978 * Math.pow(y_prime, 2) -
  		  0.002528 * Math.pow(x_prime, 2) -
  		  0.0447 * Math.pow(y_prime, 2) * x_prime -
  		  0.0140 * Math.pow(x_prime, 3);
  	
  	return new Array(lat*100/36 , lng*100/36);
  }


 /*
  * Array(Integer, Integer) coordsToSwissGrid(Double lat, Double lng)
  *
  * Transforms a coordinate from the world coordinate system to
  * the swiss grid coordinate system.
  *
  * Takes the doubles latitude and longitude as input and returns
  * an array of two integers as output.
  *
  * var result = coordsToSwissGrid(46.951081, 7.438637);
  *
  * result now contains 600000, 200000
  *
  */
  function coordsToSwissGrid(lat, lng)
  {
    // Calculate some helper values
  	var lat_helper = (toSexagesimalSec(lat) - 169028.66) / 10000;
  	var lng_helper = (toSexagesimalSec(lng) - 26782.5) / 10000;
  	
  	var x = 200147.07 + 
  		308807.95 * lat_helper +
  		3745.25 * Math.pow(lng_helper,2) +
  		76.63 * Math.pow(lat_helper,2) +
  		119.79 * Math.pow(lat_helper,3) -
  		194.56 * Math.pow(lng_helper,2) * lat_helper;
  	
  	var y = 600072.37  +
  		211455.93 * lng_helper -
  		10938.51 * lng_helper * lat_helper -
  		0.36 * lng_helper * Math.pow(lat_helper, 2) -
  		44.54 * Math.pow(lng_helper, 3);
  	
  	return new Array(Math.round(y),Math.round(x));
  }
