304 lines
10 KiB
JavaScript
Executable File
304 lines
10 KiB
JavaScript
Executable File
var datumName = "WGS 84";
|
|
var a;
|
|
var eccSquared;
|
|
var status = false;
|
|
|
|
function UTMLatLng (datumNameIn){
|
|
|
|
if (datumNameIn !== undefined)
|
|
{
|
|
datumName = datumNameIn;
|
|
}
|
|
this.setEllipsoid(datumName);
|
|
}
|
|
|
|
UTMLatLng.prototype.convertLatLngToUtm = function (latitude, longitude){
|
|
if (this.status)
|
|
{
|
|
return 'No ecclipsoid data associated with unknown datum: ' + datumName;
|
|
}
|
|
|
|
latitude = parseFloat(latitude);
|
|
longitude = parseFloat(longitude);
|
|
|
|
var LongTemp = longitude;
|
|
var LatRad = this.toRadians(latitude);
|
|
var LongRad = this.toRadians(LongTemp);
|
|
|
|
if (LongTemp >= 8 && LongTemp <= 13 && latitude > 54.5 && latitude < 58) {
|
|
ZoneNumber = 32;
|
|
} else if (latitude >= 56.0 && latitude < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0) {
|
|
ZoneNumber = 32;
|
|
} else {
|
|
ZoneNumber = ((LongTemp + 180) / 6) + 1;
|
|
|
|
if (latitude >= 72.0 && latitude < 84.0) {
|
|
if (LongTemp >= 0.0 && LongTemp < 9.0) {
|
|
ZoneNumber = 31;
|
|
} else if (LongTemp >= 9.0 && LongTemp < 21.0) {
|
|
ZoneNumber = 33;
|
|
} else if (LongTemp >= 21.0 && LongTemp < 33.0) {
|
|
ZoneNumber = 35;
|
|
} else if (LongTemp >= 33.0 && LongTemp < 42.0) {
|
|
ZoneNumber = 37;
|
|
}
|
|
}
|
|
}
|
|
ZoneNumber = parseInt(ZoneNumber);
|
|
|
|
var LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin in middle of zone
|
|
var LongOriginRad = this.toRadians(LongOrigin);
|
|
|
|
var UTMZone = this.getUtmLetterDesignator(latitude);
|
|
|
|
var eccPrimeSquared = (this.eccSquared) / (1 - this.eccSquared);
|
|
|
|
var N = this.a / Math.sqrt(1 - this.eccSquared * Math.sin(LatRad) * Math.sin(LatRad));
|
|
var T = Math.tan(LatRad) * Math.tan(LatRad);
|
|
var C = eccPrimeSquared * Math.cos(LatRad) * Math.cos(LatRad);
|
|
var A = Math.cos(LatRad) * (LongRad - LongOriginRad);
|
|
|
|
var M = this.a * ((1 - this.eccSquared / 4 - 3 * this.eccSquared * this.eccSquared / 64 - 5 * this.eccSquared * this.eccSquared * this.eccSquared / 256) * LatRad
|
|
- (3 * this.eccSquared / 8 + 3 * this.eccSquared * this.eccSquared / 32 + 45 * this.eccSquared * this.eccSquared * this.eccSquared / 1024) * Math.sin(2 * LatRad)
|
|
+ (15 * this.eccSquared * this.eccSquared / 256 + 45 * this.eccSquared * this.eccSquared * this.eccSquared / 1024) * Math.sin(4 * LatRad)
|
|
- (35 * this.eccSquared * this.eccSquared * this.eccSquared / 3072) * Math.sin(6 * LatRad));
|
|
|
|
var UTMEasting = parseFloat(0.9996 * N * (A + (1 - T + C) * A * A * A / 6
|
|
+ (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120)
|
|
+ 500000.0);
|
|
|
|
var UTMNorthing = parseFloat(0.9996 * (M + N * Math.tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24
|
|
+ (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720)));
|
|
|
|
if (latitude < 0)
|
|
UTMNorthing += 10000000.0;
|
|
UTMNorthing = parseInt(Math.round(UTMNorthing));
|
|
UTMEasting = parseInt(Math.round(UTMEasting));
|
|
return {Easting: UTMEasting, Northing: UTMNorthing, ZoneNumber: parseInt(ZoneNumber), ZoneLetter: UTMZone};
|
|
|
|
|
|
};
|
|
|
|
UTMLatLng.prototype.convertUtmToLatLng = function (UTMEasting, UTMNorthing, UTMZoneNumber, UTMZoneLetter){
|
|
var e1 = (1 - Math.sqrt(1 - this.eccSquared)) / (1 + Math.sqrt(1 - this.eccSquared));
|
|
var x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
|
|
var y = UTMNorthing;
|
|
var ZoneNumber = UTMZoneNumber;
|
|
var ZoneLetter = UTMZoneLetter;
|
|
var NorthernHemisphere;
|
|
if(UTMEasting===undefined)
|
|
{
|
|
return "Please pass the UTMEasting!";
|
|
}
|
|
if(UTMNorthing===undefined)
|
|
{
|
|
return "Please pass the UTMNorthing!";
|
|
}
|
|
if(UTMZoneNumber===undefined)
|
|
{
|
|
return "Please pass the UTMZoneNumber!";
|
|
}
|
|
if(UTMZoneLetter===undefined)
|
|
{
|
|
return "Please pass the UTMZoneLetter!";
|
|
}
|
|
|
|
if ('N' === ZoneLetter) {
|
|
NorthernHemisphere = 1;
|
|
} else {
|
|
NorthernHemisphere = 0;
|
|
this.y -= 10000000.0;
|
|
}
|
|
|
|
var LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3;
|
|
|
|
var eccPrimeSquared = (this.eccSquared) / (1 - this.eccSquared);
|
|
|
|
M = y / 0.9996;
|
|
var mu = M / (this.a * (1 - this.eccSquared / 4 - 3 * this.eccSquared * this.eccSquared / 64 - 5 * this.eccSquared * this.eccSquared * this.eccSquared / 256));
|
|
|
|
var phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.sin(2 * mu)
|
|
+ (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.sin(4 * mu)
|
|
+ (151 * e1 * e1 * e1 / 96) * Math.sin(6 * mu);
|
|
var phi1 = this.toDegrees(phi1Rad);
|
|
|
|
var N1 = this.a / Math.sqrt(1 - this.eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad));
|
|
var T1 = Math.tan(phi1Rad) * Math.tan(phi1Rad);
|
|
var C1 = eccPrimeSquared * Math.cos(phi1Rad) * Math.cos(phi1Rad);
|
|
var R1 = this.a * (1 - this.eccSquared) / Math.pow(1 - this.eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5);
|
|
var D = x / (N1 * 0.9996);
|
|
|
|
var Lat = phi1Rad - (N1 * Math.tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24
|
|
+ (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720);
|
|
Lat = this.toDegrees(Lat);
|
|
|
|
var Long = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1)
|
|
* D * D * D * D * D / 120) / Math.cos(phi1Rad);
|
|
Long = LongOrigin + this.toDegrees(Long);
|
|
return {lat: Lat, lng: Long};
|
|
};
|
|
|
|
UTMLatLng.prototype.getUtmLetterDesignator = function (latitude) {
|
|
latitude = parseFloat(latitude);
|
|
if ((84 >= latitude) && (latitude >= 72))
|
|
return 'X';
|
|
else if ((72 > latitude) && (latitude >= 64))
|
|
return 'W';
|
|
else if ((64 > latitude) && (latitude >= 56))
|
|
return 'V';
|
|
else if ((56 > latitude) && (latitude >= 48))
|
|
return 'U';
|
|
else if ((48 > latitude) && (latitude >= 40))
|
|
return 'T';
|
|
else if ((40 > latitude) && (latitude >= 32))
|
|
return 'S';
|
|
else if ((32 > latitude) && (latitude >= 24))
|
|
return 'R';
|
|
else if ((24 > latitude) && (latitude >= 16))
|
|
return 'Q';
|
|
else if ((16 > latitude) && (latitude >= 8))
|
|
return 'P';
|
|
else if ((8 > latitude) && (latitude >= 0))
|
|
return 'N';
|
|
else if ((0 > latitude) && (latitude >= -8))
|
|
return 'M';
|
|
else if ((-8 > latitude) && (latitude >= -16))
|
|
return 'L';
|
|
else if ((-16 > latitude) && (latitude >= -24))
|
|
return 'K';
|
|
else if ((-24 > latitude) && (latitude >= -32))
|
|
return 'J';
|
|
else if ((-32 > latitude) && (latitude >= -40))
|
|
return 'H';
|
|
else if ((-40 > latitude) && (latitude >= -48))
|
|
return 'G';
|
|
else if ((-48 > latitude) && (latitude >= -56))
|
|
return 'F';
|
|
else if ((-56 > latitude) && (latitude >= -64))
|
|
return 'E';
|
|
else if ((-64 > latitude) && (latitude >= -72))
|
|
return 'D';
|
|
else if ((-72 > latitude) && (latitude >= -80))
|
|
return 'C';
|
|
else
|
|
return 'Z';
|
|
|
|
};
|
|
|
|
UTMLatLng.prototype.setEllipsoid = function (name){
|
|
switch (name) {
|
|
case 'Airy':
|
|
this.a = 6377563;
|
|
this.eccSquared = 0.00667054;
|
|
break;
|
|
case 'Australian National':
|
|
this.a = 6378160;
|
|
this.eccSquared = 0.006694542;
|
|
break;
|
|
case 'Bessel 1841':
|
|
this.a = 6377397;
|
|
this.eccSquared = 0.006674372;
|
|
break;
|
|
case 'Bessel 1841 Nambia':
|
|
this.a = 6377484;
|
|
this.eccSquared = 0.006674372;
|
|
break;
|
|
case 'Clarke 1866':
|
|
this.a = 6378206;
|
|
this.eccSquared = 0.006768658;
|
|
break;
|
|
case 'Clarke 1880':
|
|
this.a = 6378249;
|
|
this.eccSquared = 0.006803511;
|
|
break;
|
|
case 'Everest':
|
|
this.a = 6377276;
|
|
this.eccSquared = 0.006637847;
|
|
break;
|
|
case 'Fischer 1960 Mercury':
|
|
this.a = 6378166;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'Fischer 1968':
|
|
this.a = 6378150;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'GRS 1967':
|
|
this.a = 6378160;
|
|
this.eccSquared = 0.006694605;
|
|
break;
|
|
case 'GRS 1980':
|
|
this.a = 6378137;
|
|
this.eccSquared = 0.00669438;
|
|
break;
|
|
case 'Helmert 1906':
|
|
this.a = 6378200;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'Hough':
|
|
this.a = 6378270;
|
|
this.eccSquared = 0.00672267;
|
|
break;
|
|
case 'International':
|
|
this.a = 6378388;
|
|
this.eccSquared = 0.00672267;
|
|
break;
|
|
case 'Krassovsky':
|
|
this.a = 6378245;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'Modified Airy':
|
|
this.a = 6377340;
|
|
this.eccSquared = 0.00667054;
|
|
break;
|
|
case 'Modified Everest':
|
|
this.a = 6377304;
|
|
this.eccSquared = 0.006637847;
|
|
break;
|
|
case 'Modified Fischer 1960':
|
|
this.a = 6378155;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'South American 1969':
|
|
this.a = 6378160;
|
|
this.eccSquared = 0.006694542;
|
|
break;
|
|
case 'WGS 60':
|
|
this.a = 6378165;
|
|
this.eccSquared = 0.006693422;
|
|
break;
|
|
case 'WGS 66':
|
|
this.a = 6378145;
|
|
this.eccSquared = 0.006694542;
|
|
break;
|
|
case 'WGS 72':
|
|
this.a = 6378135;
|
|
this.eccSquared = 0.006694318;
|
|
break;
|
|
case 'ED50':
|
|
this.a = 6378388;
|
|
this.eccSquared = 0.00672267;
|
|
break; // International Ellipsoid
|
|
case 'WGS 84':
|
|
case 'EUREF89': // Max deviation from WGS 84 is 40 cm/km see http://ocq.dk/euref89 (in danish)
|
|
case 'ETRS89': // Same as EUREF89
|
|
this.a = 6378137;
|
|
this.eccSquared = 0.00669438;
|
|
break;
|
|
default:
|
|
this.status = true;
|
|
// new Error('No ecclipsoid data associated with unknown datum: '.name);
|
|
|
|
}
|
|
};
|
|
|
|
UTMLatLng.prototype.toDegrees = function (rad) {
|
|
|
|
return rad / Math.PI * 180;
|
|
};
|
|
|
|
UTMLatLng.prototype.toRadians = function (deg) {
|
|
|
|
return deg * Math.PI / 180;
|
|
};
|