/* * Author: Sami Salkosuo, sami.salkosuo@fi.ibm.com * * (c) Copyright IBM Corp. 2007 */ package de.tud.kom.p2psim.impl.util.geo.maps.osm; import static java.lang.Math.cos; import static java.lang.Math.pow; import static java.lang.Math.sin; import static java.lang.Math.tan; import de.tud.kom.p2psim.impl.topology.util.PositionVector; /** * This class can be used to convert lat/lon coordinates to * utm coordinates. * * It is a stripped down version of the one found at * http://www.ibm.com/developerworks/java/library/j-coordconvert/ * Original author: Sami Salkosuo, sami.salkosuo@fi.ibm.com * * @author Fabio Zöllner * @version 1.0, 09.05.2012 */ @SuppressWarnings("synthetic-access") public class UTMConversion { private static final double r2d = 180 / Math.PI; private static final double d2r = Math.PI / 180; public UTMConversion() { } public static UTM latLon2UTM(double latitude, double longitude) { LatLon2UTM c = new LatLon2UTM(); return c.convertLatLonToUTM(latitude, longitude); } private static void validate(double latitude, double longitude) { if (latitude < -90.0 || latitude > 90.0 || longitude < -180.0 || longitude >= 180.0) { throw new IllegalArgumentException( "Legal ranges: latitude [-90,90], longitude [-180,180)."); } } public static double degreeToRadian(double degree) { return degree * d2r; } public double radianToDegree(double radian) { return radian * r2d; } private static class LatLon2UTM { public UTM convertLatLonToUTM(double latitude, double longitude) { validate(latitude, longitude); UTM utm = null; setVariables(latitude, longitude); String longZone = getLongZone(longitude); LatZones latZones = new LatZones(); String latZone = latZones.getLatZone(latitude); double _easting = getEasting(); double _northing = getNorthing(latitude); utm = new UTM(new PositionVector(_easting, _northing), longZone, latZone); return utm; } protected void setVariables(double latitude, double longitude) { latitude = degreeToRadian(latitude); rho = equatorialRadius * (1 - e * e) / pow(1 - pow(e * sin(latitude), 2), 3 / 2.0); nu = equatorialRadius / pow(1 - pow(e * sin(latitude), 2), (1 / 2.0)); double var1; if (longitude < 0.0) { var1 = ((int) ((180 + longitude) / 6.0)) + 1; } else { var1 = ((int) (longitude / 6)) + 31; } double var2 = (6 * var1) - 183; double var3 = longitude - var2; p = var3 * 3600 / 10000; S = A0 * latitude - B0 * sin(2 * latitude) + C0 * sin(4 * latitude) - D0 * sin(6 * latitude) + E0 * sin(8 * latitude); K1 = S * k0; K2 = nu * sin(latitude) * cos(latitude) * pow(sin1, 2) * k0 * (100000000) / 2; K3 = ((pow(sin1, 4) * nu * sin(latitude) * Math.pow(cos(latitude), 3)) / 24) * (5 - pow(tan(latitude), 2) + 9 * e1sq * pow(cos(latitude), 2) + 4 * pow(e1sq, 2) * pow(cos(latitude), 4)) * k0 * (10000000000000000L); K4 = nu * cos(latitude) * sin1 * k0 * 10000; K5 = pow(sin1 * cos(latitude), 3) * (nu / 6) * (1 - pow(tan(latitude), 2) + e1sq * pow(cos(latitude), 2)) * k0 * 1000000000000L; A6 = (pow(p * sin1, 6) * nu * sin(latitude) * pow(cos(latitude), 5) / 720) * (61 - 58 * pow(tan(latitude), 2) + pow(tan(latitude), 4) + 270 * e1sq * pow(cos(latitude), 2) - 330 * e1sq * pow(sin(latitude), 2)) * k0 * (1E+24); } protected String getLongZone(double longitude) { double longZone = 0; if (longitude < 0.0) { longZone = ((180.0 + longitude) / 6) + 1; } else { longZone = (longitude / 6) + 31; } String val = String.valueOf((int) longZone); if (val.length() == 1) { val = "0" + val; } return val; } protected double getNorthing(double latitude) { double northing = K1 + K2 * p * p + K3 * pow(p, 4); if (latitude < 0.0) { northing = 10000000 + northing; } return northing; } protected double getEasting() { return 500000 + (K4 * p + K5 * pow(p, 3)); } // Lat Lon to UTM variables // equatorial radius double equatorialRadius = 6378137; // polar radius double polarRadius = 6356752.314; // scale factor double k0 = 0.9996; // eccentricity double e = Math.sqrt(1 - pow(polarRadius / equatorialRadius, 2)); double e1sq = e * e / (1 - e * e); // r curv 1 double rho = 6368573.744; // r curv 2 double nu = 6389236.914; // Calculate Meridional Arc Length // Meridional Arc double S = 5103266.421; double A0 = 6367449.146; double B0 = 16038.42955; double C0 = 16.83261333; double D0 = 0.021984404; double E0 = 0.000312705; // Calculation Constants // Delta Long double p = -0.483084; double sin1 = 4.84814E-06; // Coefficients for UTM Coordinates double K1 = 5101225.115; double K2 = 3750.291596; double K3 = 1.397608151; double K4 = 214839.3105; double K5 = -2.995382942; double A6 = -1.00541E-07; } private static class LatZones { private char[] letters = { 'A', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Z' }; private int[] degrees = { -90, -84, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 84 }; private char[] negLetters = { 'A', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M' }; private int[] negDegrees = { -90, -84, -72, -64, -56, -48, -40, -32, -24, -16, -8 }; private char[] posLetters = { 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Z' }; private int[] posDegrees = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 84 }; private int arrayLength = 22; public LatZones() { } public String getLatZone(double latitude) { int latIndex = -2; int lat = (int) latitude; if (lat >= 0) { int len = posLetters.length; for (int i = 0; i < len; i++) { if (lat == posDegrees[i]) { latIndex = i; break; } if (lat > posDegrees[i]) { continue; } else { latIndex = i - 1; break; } } } else { int len = negLetters.length; for (int i = 0; i < len; i++) { if (lat == negDegrees[i]) { latIndex = i; break; } if (lat < negDegrees[i]) { latIndex = i - 1; break; } else { continue; } } } if (latIndex == -1) { latIndex = 0; } if (lat >= 0) { if (latIndex == -2) { latIndex = posLetters.length - 1; } return String.valueOf(posLetters[latIndex]); } else { if (latIndex == -2) { latIndex = negLetters.length - 1; } return String.valueOf(negLetters[latIndex]); } } } }