GridReferenceConverter.java from GridBlocks at Krugle
Show GridReferenceConverter.java syntax highlighted
//-----------------------------------------------------------------------------
// GridReferenceConverter.java
//
// (c) 2003 Jonathan Stott
//
// 0.2 - 02 Mar 2004
// - Added ability to convert UTM to/from latitude/longitude
// - Added ability to convert OSGB grid references to/from latitude/longitude
// 0.1 - 11 Nov 2003
// - First version
//-----------------------------------------------------------------------------
package fi.hip.gb.bluetooth.coordconv;
/**
* Convert latitude/longitude to UTM references and vice/versa.
*
* Based on algorithm published by the Ordnance Survey at
* http://www.gps.gov.uk/guidecontents.asp
*
* @author Jonathan Stott
* @version 0.2
*/
public class GridReferenceConverter {
private static final double UTM_F0 = 0.9996;
/**
* Convert an UTM reference to a latitude and longitude
*
* @param ellipsoid A reference ellipsoid to use
* @param utm the UTM reference to convert
* @return the converted latitude and longitude
* @since 0.2
*/
public static LatitudeLongitude UTMReferenceToLatitudeLongitude(
ReferenceEllipsoid ellipsoid,
UTMReference utm) {
double a = ellipsoid.getSemiMajorAxis();
double eSquared = ellipsoid.getEccentricitySquared();
double ePrimeSquared = eSquared / (1.0 - eSquared);
double e1 = (1 - sqrt(1 - eSquared)) / (1 + sqrt(1 - eSquared));
double x = utm.getEasting() - 500000.0;;
double y = utm.getNorthing();
int zoneNumber = utm.getLongitudeZone();
char zoneLetter = utm.getLatitudeZone();
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
* pow(eSquared, 3.0)
/ 256.0));
double phi1Rad =
mu
+ (3.0 * e1 / 2.0 - 27.0 * pow(e1, 3.0) / 32.0) * sin(2.0 * mu)
+ (21.0 * e1 * e1 / 16.0 - 55.0 * pow(e1, 4.0) / 32.0)
* sin(4.0 * mu)
+ (151.0 * pow(e1, 3.0) / 96.0) * sin(6.0 * mu);
double n =
a
/ sqrt(1.0 - eSquared * sin(phi1Rad) * sin(phi1Rad));
double t = tan(phi1Rad) * tan(phi1Rad);
double c = ePrimeSquared * cos(phi1Rad) * cos(phi1Rad);
double r =
a
* (1.0 - eSquared)
/ pow(
1.0 - eSquared * sin(phi1Rad) * sin(phi1Rad),
1.5);
double d = x / (n * UTM_F0);
double latitude = (
phi1Rad
- (n * tan(phi1Rad) / r)
* (d * d / 2.0
- (5.0
+ (3.0 * t)
+ (10.0 * c)
- (4.0 * c * c)
- (9.0 * ePrimeSquared))
* 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))
* pow(d, 6.0)
/ 720.0)) * (180.0 / Math.PI);
double longitude = longitudeOrigin + (
(d
- (1.0 + 2.0 * t + c) * 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))
* pow(d, 5.0)
/ 120.0)
/ cos(phi1Rad)) * (180.0 / Math.PI);
return new LatitudeLongitude(new Float(latitude), new Float(longitude));
}
/**
* Convert a latitude and longitude to an UTM reference
*
* @param ellipsoid A reference ellipsoid to use
* @param latitudeLongitude The latitude and longitude to convert
* @return the converted UTM reference
* @since 0.2
*/
public static UTMReference latitudeLongitudeToUTMReference(
ReferenceEllipsoid ellipsoid,
LatitudeLongitude latitudeLongitude) {
int longitudeZone =
(int) ((latitudeLongitude.getLongitude().floatValue() + 180.0) / 6.0) + 1;
char UTMZone = getUTMLatitudeZoneLetter(latitudeLongitude.getLatitude());
return latitudeLongitudeToUTMReference(ellipsoid, latitudeLongitude, longitudeZone, UTMZone);
}
/**
* Convert a latitude and longitude to an UTM reference
*
* @param ellipsoid A reference ellipsoid to use
* @param latitudeLongitude The latitude and longitude to convert
* @param longitudeZone longitude zone
* @param UTMZone latitude zone
* @return the converted UTM reference
* @since 0.2
*/
public static UTMReference latitudeLongitudeToUTMReference(
ReferenceEllipsoid ellipsoid,
LatitudeLongitude latitudeLongitude,
int longitudeZone,
char UTMZone) {
double a = ellipsoid.getSemiMajorAxis();
double eSquared = ellipsoid.getEccentricitySquared();
float longitude = latitudeLongitude.getLongitude().floatValue();
float latitude = latitudeLongitude.getLatitude().floatValue();
double latitudeRad = latitude * (Math.PI / 180.0);
double longitudeRad = longitude * (Math.PI / 180.0);
//int longitudeZone = (int) ((longitude + 180.0) / 6.0) + 1;
// Special zone for Norway
if (latitude >= 56.0
&& latitude < 64.0
&& longitude >= 3.0
&& longitude < 12.0) {
longitudeZone = 32;
}
// Special zones for Svalbard
if (latitude >= 72.0 && latitude < 84.0) {
if (longitude >= 0.0 && longitude < 9.0) {
longitudeZone = 31;
} else if (longitude >= 9.0 && longitude < 21.0) {
longitudeZone = 33;
} else if (longitude >= 21.0 && longitude < 33.0) {
longitudeZone = 35;
} else if (longitude >= 33.0 && longitude < 42.0) {
longitudeZone = 37;
}
}
double longitudeOrigin = (longitudeZone - 1) * 6 - 180 + 3;
double longitudeOriginRad = longitudeOrigin * (Math.PI / 180.0);
//char UTMZone = getUTMLatitudeZoneLetter(latitude);
double ePrimeSquared = (eSquared) / (1 - eSquared);
double n = a / sqrt(1 - eSquared * sin(latitudeRad) * sin(latitudeRad));
double t = tan(latitudeRad) * tan(latitudeRad);
double c = ePrimeSquared * cos(latitudeRad) * cos(latitudeRad);
double A = cos(latitudeRad) * (longitudeRad - longitudeOriginRad);
double M =
a
* ((1
- eSquared / 4
- 3 * eSquared * eSquared / 64
- 5 * eSquared * eSquared * eSquared / 256)
* latitudeRad
- (3 * eSquared / 8
+ 3 * eSquared * eSquared / 32
+ 45 * eSquared * eSquared * eSquared / 1024)
* sin(2 * latitudeRad)
+ (15 * eSquared * eSquared / 256
+ 45 * eSquared * eSquared * eSquared / 1024)
* sin(4 * latitudeRad)
- (35 * eSquared * eSquared * eSquared / 3072)
* sin(6 * latitudeRad));
double UTMEasting =
(double) (UTM_F0
* n
* (A
+ (1 - t + c) * pow(A, 3.0) / 6
+ (5 - 18 * t + t * t + 72 * c - 58 * ePrimeSquared)
* pow(A, 5.0)
/ 120)
+ 500000.0);
double UTMNorthing =
(double) (UTM_F0
* (M
+ n
* tan(latitudeRad)
* (A * A / 2
+ (5 - t + (9 * c) + (4 * c * c)) * pow(A, 4.0) / 24
+ (61 - (58 * t) + (t * t) + (600 * c) - (330 * ePrimeSquared))
* pow(A, 6.0)
/ 720)));
// Adjust for the southern hemisphere
if (latitude < 0) {
UTMNorthing += 10000000.0;
}
return new UTMReference(UTMEasting, UTMNorthing, UTMZone, longitudeZone);
}
/**
* Work out the UTM latitude zone from the latitude
*
* @param latitude
* @return
* @since 0.2
*/
public static char getUTMLatitudeZoneLetter(Float lat) {
float latitude = lat.floatValue();
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';
}
/**
* Calculate sin(x)
*
* @param x
* @return
* @since 0.1
*/
private static double sin(double x) {
return Math.sin(x);
}
/**
* Calculate sin^2(x)
*
* @param x
* @return
* @since 0.1
*/
private static double sinSquared(double x) {
return sin(x) * sin(x);
}
/**
* Calculate cos(x)
*
* @param x
* @return
* @since 0.1
*/
private static double cos(double x) {
return Math.cos(x);
}
/**
* Calculate tan(x)
*
* @param x
* @return
* @since 0.1
*/
private static double tan(double x) {
return Math.tan(x);
}
/**
* Calculate tan^2(x)
*
* @param x
* @return
* @since 0.1
*/
private static double tanSquared(double x) {
return tan(x) * tan(x);
}
/**
* Calculate sec(x)
*
* @param x
* @return
* @since 0.1
*/
private static double sec(double x) {
return 1.0 / cos(x);
}
/**
* Calculate x^e
*
* @param x
* @param e
* @return
* @since 0.1
*/
private static double pow(double x, double e) {
return Math.pow(x, e);
}
/**
* Calculate sqrt(x)
*
* @param x
* @return
* @since 0.2
*/
private static double sqrt(double x) {
return Math.sqrt(x);
}
}
See more files for this project here