//utm.js
//http://www.koders.com/javascript/fidD885FBA9851752CB9597A50817A13E1E81E4B011.aspx?s=Point#L27
//corrected with : http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
// so UTMToGeographic() works in south hemisphere

// Point and Polygon classes.
//
function DmsPoint(x, y)
{
  this.x = x;
  this.y = y;
}



////////////////////////////////////////////////

// Functions to convert between lat,lon and utm. Derived from visual basic
// routines from Craig Perault. This assumes a NAD83 datum.

// constants
var MajorAxis = 6378137.0;
var MinorAxis = 6356752.3;
var Ecc = (MajorAxis * MajorAxis - MinorAxis * MinorAxis) / (MajorAxis * MajorAxis);
var Ecc2 = Ecc / (1.0 - Ecc);
var K0 = 0.9996;
var E4 = Ecc * Ecc;
var E6 = Ecc * E4;
var degrees2radians = Math.PI / 180.0;

// Computes the meridian distance for the GRS-80 Spheroid.
// See equation 3-22, USGS Professional Paper 1395.
function meridianDist(lat) {
  var c1 = MajorAxis * (1 - Ecc / 4 - 3 * E4 / 64 - 5 * E6 / 256);
  var c2 = -MajorAxis * (3 * Ecc / 8 + 3 * E4 / 32 + 45 * E6 / 1024);
  var c3 = MajorAxis * (15 * E4 / 256 + 45 * E6 / 1024);
  var c4 = -MajorAxis * 35 * E6 / 3072;

  return(c1 * lat + c2 * Math.sin(lat * 2) + c3 * Math.sin(lat * 4) + c4 * Math.sin(lat * 6));
}

// Convert lat/lon (given in decimal degrees) to UTM, given a particular UTM zone.
function geographicToUTM(zone, latlon) {
  var utm = new DmsPoint();
	
  var centeralMeridian = -((30 - zone) * 6 + 3) * degrees2radians;

  var lat = latlon.y * degrees2radians;
  var lon = latlon.x * degrees2radians;

  var latSin = Math.sin(lat);
  var latCos = Math.cos(lat);
  var latTan = latSin / latCos;
  var latTan2 = latTan * latTan;
  var latTan4 = latTan2 * latTan2;

  var N = MajorAxis / Math.sqrt(1 - Ecc * (latSin*latSin));
  var c = Ecc2 * latCos*latCos;
  var a = latCos * (lon - centeralMeridian);
  var m = meridianDist(lat);

  var temp5 = 1.0 - latTan2 + c;
  var temp6 = 5.0 - 18.0 * latTan2 + latTan4 + 72.0 * c - 58.0 * Ecc2;
  var temp11 = Math.pow(a, 5);

  utm.x = K0 * N * (a + (temp5 * Math.pow(a, 3)) / 6.0 + temp6 * temp11 / 120.0) + 500000;

  var temp7 = (5.0 - latTan2 + 9.0 * c + 4.0 * (c*c)) * Math.pow(a,4) / 24.0;
  var temp8 = 61.0 - 58.0 * latTan2 + latTan4 + 600.0 * c - 330.0 * Ecc2;
  var temp9 = temp11 * a / 720.0;

  utm.y = K0 * (m + N * latTan * ((a * a) / 2.0 + temp7 + temp8 * temp9))

  return(utm);
}


function CSq(value) {
  return value*value;
}

// Convert UTM coordinates (given in meters) to Lat/Lon (in decimal degrees), given a particular UTM zone.
function UTMToGeographic(zone, utm_param,southhemi) {
  var latlon = new DmsPoint();
  var utm =new DmsPoint(utm_param.x,utm_param.y);
  
  var centeralMeridian = -((30 - zone) * 6 + 3) * degrees2radians;

  var temp1 = Math.sqrt(1.0 - Ecc);
  var ecc1 = (1.0 - temp1) / (1.0 + temp1);
  var ecc12 = ecc1 * ecc1;
  var ecc13 = ecc1 * ecc12;
  var ecc14 = ecc12 * ecc12;

  utm.x = utm.x - 500000.0;
  if (southhemi)
   {utm.y -= 10000000.0;}

  var m = utm.y / K0;
  var um = m / (MajorAxis * (1.0 - (Ecc / 4.0) - 3.0 * (E4 / 64.0) - 5.0 * (E6 / 256.0)));

  var temp8 = (1.5 * ecc1) - (27.0 / 32.0) * ecc13;
  var temp9 = ((21.0 / 16.0) * ecc12) - ((55.0 / 32.0) * ecc14);

  var latrad1 = um + temp8 * Math.sin(2 * um) + temp9 * Math.sin(4 * um) + (151.0 * ecc13 / 96.0) * Math.sin(6.0 * um);

  var latsin1 = Math.sin(latrad1);
  var latcos1 = Math.cos(latrad1);
  var lattan1 = latsin1 / latcos1;
  var n1 = MajorAxis / Math.sqrt(1.0 - Ecc * CSq(latsin1));
  var t2 = CSq(lattan1);
  var c1 = Ecc2 * CSq(latcos1);

  var temp20 = (1.0 - Ecc * CSq(latsin1));
  var r1 = MajorAxis * (1.0 - Ecc) / Math.sqrt(CSq(temp20) * temp20);

  var d1 = utm.x / (n1*K0);
  var d2 = CSq(d1);
  var d3 = d1 * d2;
  var d4 = CSq(d2);
  var d5 = d1 * d4;
  var d6 = CSq(d3);

  var t12 = CSq(t2);
  var c12 = CSq(c1);

  temp1 = n1 * lattan1 / r1;
  temp2 = 5.0 + 3.0 * t2 + 10.0 * c1 - 4.0 * c12 - 9.0 * Ecc2;
  temp4 = 61.0 + 90.0 * t2 + 298.0 * c1 + 45.0 * t12 - 252.0 * Ecc2 - 3.0 * c12;
  temp5 = (1.0 + 2.0 * t2 + c1) * d3 / 6.0;
  temp6 = 5.0 - 2.0 * c1 + 28.0 * t2 - 3.0 * c12 + 8.0 * Ecc2 + 24.0 * t12;

  latlon.y = (latrad1 - temp1 * (d2 / 2.0 - temp2 * (d4 / 24.0) + temp4 * d6 / 720.0)) * 180 / Math.PI;
  latlon.x = (centeralMeridian + (d1 - temp5 + temp6 * d5 / 120.0) / latcos1) * 180 / Math.PI;
  utm.x = utm.x + 500000.0;

  return(latlon);
}

//end utm.js


//calcDistance:http://javascript.internet.com/math-related/latitude-longitude-converter.html
function calcDistance(lat1, lon1, lat2, lon2, unit) {
	var radlat1 = Math.PI * lat1/180
	var radlat2 = Math.PI * lat2/180
	var radlon1 = Math.PI * lon1/180
	var radlon2 = Math.PI * lon2/180
	var theta = lon1-lon2
	var radtheta = Math.PI * theta/180
	var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
	dist = Math.acos(dist)
	dist = dist * 180/Math.PI
	dist = dist * 60 * 1.1515
	if (unit=="M") { dist = dist * 1.609344 * 1000}
	if (unit=="K") { dist = dist * 1.609344 }
	if (unit=="N") { dist = dist * 0.8684 }
	return dist
} 




Feature.prototype.getLengthUsingDegrees = function() {
  var measure = 0;
  for (var i = 0; i<this.vertices.length - 1; i++) {
  measure += calcDistance(this.vertices[i].y,this.vertices[i].x,this.vertices[i+1].y,this.vertices[i+1].x,'M');
  }
  return measure;
};

Feature.prototype.getLength = function() {
var measure = 0;
if (this.proj =='utm'){
  //code copied from Feature.prototype.getLength in dhtmlFeatures.js
  for (var i = 0; i<this.vertices.length - 1; i++) {
    var dist_x = this.vertices[i].x - this.vertices[i+1].x;
    var dist_y = this.vertices[i].y - this.vertices[i+1].y;
    measure += Math.sqrt(dist_x * dist_x + dist_y * dist_y);
  }
  
 }else
 {
 measure = this.getLengthUsingDegrees();
} 
  return measure;
};



Feature.prototype.getArea = function() {
var measure = 0;
if (this.proj =='utm'){
  //code copied from Feature.prototype.getArea in dhtmlFeatures.js
  //TODO area for circle
  if (this.vertices.length > 1) {
    //surface calculation
    var measure = 0;
    for (var i = 0; i<this.vertices.length - 1;i++)
      measure += this.vertices[i].x * this.vertices[i+1].y - this.vertices[i+1].x * this.vertices[i].y;
    measure += this.vertices[this.vertices.length -1].x * this.vertices[0].y - this.vertices[0].x * this.vertices[this.vertices.length -1].y;
    return Math.abs(measure) / 2;
  } else {
    return 0;
  }
  
 }else
 {
 measure = this.getAreaUsingDegrees();
} 
  return measure;
};


Feature.prototype.getAreaUsingDegrees = function() {
  //TODO area for circle
  if (this.vertices.length > 1) {
    //surface calculation
    var measure = 0;
    var coords1= null;
    var coords2= null;
    zone = getUTMZoneFromLongitude(this.vertices[0].x);
    for (var i = 0; i<this.vertices.length - 1;i++){
    coords1 = geographicToUTM( zone,new DmsPoint(this.vertices[i].x,this.vertices[i].y));
    coords2 = geographicToUTM( zone,new DmsPoint( this.vertices[i+1].x,this.vertices[i+1].y));
    measure += coords1.x * coords2.y - coords2.x * coords1.y;
    }
    coords1 = geographicToUTM( zone,new DmsPoint(this.vertices[this.vertices.length -1].x,this.vertices[this.vertices.length -1].y));
    coords2 = geographicToUTM( zone,new DmsPoint( this.vertices[0].x,this.vertices[0].y));
    measure += coords1.x * coords2.y - coords2.x * coords1.y;
    return Math.abs(measure) / 2;
  } else {
    return 0;
  }
};


function getUTMZoneFromLongitude(long)
{
zone = Math.floor ((long + 180.0) / 6) + 1;
return zone;
}

//override of Map.prototype.onMove in dhtmlInit.js

Map.prototype.resetMapEventHandlers = function() {
  if (this.onToolUnset != undefined) {
    this.onToolUnset();
  }
  this.onToolUnset = undefined;
  this.onFeatureInput = undefined;
  this.onClic = undefined;
  this.onSelPoint = undefined;
  this.onFeatureChange = undefined;
  this.onNewFeature = undefined;
  this.onCancel = function() {
    createMap();
  }
  this.onMove = function(geoX, geoY) {
   // display geo coordinates 
    if (this.geoTag)
    // modif lolo debut
     {
     var isLat=true;
     var latlong=null;
     if (Feature.prototype.proj == 'utm')
     {
    	var hemisphere=Feature.prototype.hemisphere;
    	latlong=UTMToGeographic(Feature.prototype.zone,new DmsPoint(geoX,geoY),(hemisphere == 'south'));
    	this.geoTag.innerHTML = sprintf(this.geoUnits, toDMS(latlong.y,isLat),toDMS(latlong.x,!isLat) );
  	 }
     else{
		     if (Feature.prototype.proj == 'latlong'){
			   this.geoTag.innerHTML = sprintf(this.geoUnits, toDMS(geoY,isLat),toDMS(geoX,!isLat) );
			 }
			 else{
			 	this.geoTag.innerHTML = sprintf(this.geoUnits, geoX, geoY);
			 }
	     }
     }
     //modif lolo fin
   }
};

function toDMS(deg,isLat) {
		var symbol ='';
		if (deg<0){
		if (isLat){symbol = 'S'}else{symbol = 'W'};
		}
		if (deg>0){
		if (isLat){symbol = 'N'}else{symbol = 'E'};
		}
		var absdeg = Math.abs(deg);
		var gpsdeg = parseInt(absdeg);
        var remainder = absdeg - gpsdeg * 1;
        var remainder_min = remainder * 60;
        gpsmin = parseInt(remainder_min);
        var remainder2 = remainder_min - parseInt(remainder_min) * 1;
        gpssec = parseInt(remainder2 * 60);
		var dms_str=gpsdeg+'&deg; '+gpsmin+'&prime;  '+gpssec+'&Prime;' + symbol;
		return dms_str;
}


