package uk.me.jstott.jcoord;
/**
* Class to represent a UTM reference
*
* (c) 2006 Jonathan Stott
*
* Created on 11-Feb-2006
*
* @author Jonathan Stott
* @version 1.0
* @since 1.0
*/
public class UTMRef {
/**
* Easting
*/
private double easting;
/**
* Northing
*/
private double northing;
/**
* Latitude zone character
*/
private char latZone;
/**
* Longitude zone number
*/
private int lngZone;
/**
* Create a new UTM reference object.
*
* @param easting
* the easting
* @param northing
* the northing
* @param latZone
* the latitude zone character
* @param lngZone
* the longitude zone number
* @since 1.0
*/
public UTMRef(double easting, double northing, char latZone, int lngZone) {
this.easting = easting;
this.northing = northing;
this.latZone = latZone;
this.lngZone = lngZone;
}
/**
* Convert this UTM reference to a latitude and longitude.
*
* @return the converted latitude and longitude
* @since 1.0
*/
public LatLng toLatLng() {
double UTM_F0 = 0.9996;
double a = RefEll.WGS84.getMaj();
double eSquared = RefEll.WGS84.getEcc();
double ePrimeSquared = eSquared / (1.0 - eSquared);
double e1 = (1 - Math.sqrt(1 - eSquared)) / (1 + Math.sqrt(1 - eSquared));
double x = easting - 500000.0;
;
double y = northing;
int zoneNumber = lngZone;
char zoneLetter = latZone;
double longitudeOrigin = (zoneNumber - 1.0) * 6.0 - 180.0 + 3.0;
// Correct y for southern hemisphere
if ((zoneLetter - 'N') < 0) {
y -= 10000000.0;
}
double m = y / UTM_F0;
double mu =
m
/ (a * (1.0 - eSquared / 4.0 - 3.0 * eSquared * eSquared / 64.0 - 5.0 * Math
.pow(eSquared, 3.0) / 256.0));
double phi1Rad =
mu + (3.0 * e1 / 2.0 - 27.0 * Math.pow(e1, 3.0) / 32.0)
* Math.sin(2.0 * mu)
+ (21.0 * e1 * e1 / 16.0 - 55.0 * Math.pow(e1, 4.0) / 32.0)
* Math.sin(4.0 * mu) + (151.0 * Math.pow(e1, 3.0) / 96.0)
* Math.sin(6.0 * mu);
double n =
a / Math.sqrt(1.0 - eSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad));
double t = Math.tan(phi1Rad) * Math.tan(phi1Rad);
double c = ePrimeSquared * Math.cos(phi1Rad) * Math.cos(phi1Rad);
double r =
a
* (1.0 - eSquared)
/ Math.pow(1.0 - eSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad),
1.5);
double d = x / (n * UTM_F0);
double latitude =
(phi1Rad - (n * Math.tan(phi1Rad) / r)
* (d
* d
/ 2.0
- (5.0 + (3.0 * t) + (10.0 * c) - (4.0 * c * c) - (9.0 * ePrimeSquared))
* Math.pow(d, 4.0) / 24.0 + (61.0 + (90.0 * t) + (298.0 * c)
+ (45.0 * t * t) - (252.0 * ePrimeSquared) - (3.0 * c * c))
* Math.pow(d, 6.0) / 720.0))
* (180.0 / Math.PI);
double longitude =
longitudeOrigin
+ ((d - (1.0 + 2.0 * t + c) * Math.pow(d, 3.0) / 6.0 + (5.0
- (2.0 * c) + (28.0 * t) - (3.0 * c * c)
+ (8.0 * ePrimeSquared) + (24.0 * t * t))
* Math.pow(d, 5.0) / 120.0) / Math.cos(phi1Rad))
* (180.0 / Math.PI);
return new LatLng(latitude, longitude);
}
/**
* Work out the UTM latitude zone from the latitude.
*
* @param latitude
* the latitude to find the UTM latitude zone for
* @return the UTM latitude zone for the given latitude
* @since 1.0
*/
public static char getUTMLatitudeZoneLetter(double 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';
}
/**
* Convert this UTM reference to a String representation for printing out.
*
* @return a String representation of this UTM reference
* @since 1.0
*/
public String toString() {
return lngZone + Character.toString(latZone) + " " + easting + " "
+ northing;
}
/**
* Get the easting.
*
* @return the easting
* @since 1.0
*/
public double getEasting() {
return easting;
}
/**
* Get the northing.
*
* @return the northing
* @since 1.0
*/
public double getNorthing() {
return northing;
}
/**
* Get the latitude zone character.
*
* @return the latitude zone character
* @since 1.0
*/
public char getLatZone() {
return latZone;
}
/**
* Get the longitude zone number.
*
* @return the longitude zone number
* @since 1.0
*/
public int getLngZone() {
return lngZone;
}
}