Created
March 21, 2013 20:10
-
-
Save 2sbsbsb/5216268 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.DecimalFormat; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
/** | |
* Parses longitude or latitude to double | |
*/ | |
public class LongitudeLatitudeUtil { | |
private static String EXPRESSION = "^(?<deg>[-+0-9]+)[^0-9]+(?<min>[0-9]+)[^0-9]+(?<sec>[0-9.,]+)[^0-9.,ENSW]+(?<pos>[ENSW]*)$"; | |
/** | |
* Parses the latitude and longitude to double | |
* | |
* @param value | |
* @return | |
*/ | |
public static double ParseLatLonValue(String value) { | |
double result = Double.NaN; | |
/** | |
* Remove the double quote from both sides if present | |
*/ | |
if (value.startsWith("\"") && value.endsWith("\"")) { | |
value = value.substring(1, value.length() - 2).replace("\"\"", "\""); | |
} | |
Pattern pattern = Pattern.compile(EXPRESSION); | |
Matcher matcher = pattern.matcher(value); | |
double deg = Double.NaN; | |
double min = Double.NaN; | |
double sec = Double.NaN; | |
char pos = '\0'; | |
if (matcher.matches()) { | |
deg = Double.parseDouble(matcher.group("deg")); | |
min = Double.parseDouble(matcher.group("min")); | |
sec = Double.parseDouble(matcher.group("sec")); | |
pos = matcher.group("pos").charAt(0); | |
result = parseLatLonValue(deg, min, sec, pos); | |
} | |
return result; | |
} | |
/** | |
* @param deg | |
* @param min | |
* @param sec | |
* @param pos | |
* @return | |
*/ | |
public static double parseLatLonValue(double deg, double min, double sec, char pos) { | |
double result = deg + (min / 60) + (sec / 3600); | |
// North and East are positives and so adjustment for S W | |
result = ((pos == 'S') || (pos == 'W')) ? -result : result; | |
return result; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
private static String parseLatLonValue(double value) { | |
double absoluteValue = Math.abs(value); | |
int deg = (int) Math.floor(absoluteValue); | |
absoluteValue = (absoluteValue - deg) * 60; | |
int min = (int) Math.floor(absoluteValue); | |
double seconds = (absoluteValue - min) * 60; | |
DecimalFormat twoDForm = new DecimalFormat("#.##"); | |
seconds = Double.valueOf(twoDForm.format(seconds)); | |
return deg + "°" + min + "'" + seconds; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
private static String parseSpaceLatLonValue(double value) { | |
double absoluteValue = Math.abs(value); | |
int deg = (int) Math.floor(absoluteValue); | |
absoluteValue = (absoluteValue - deg) * 60; | |
int min = (int) Math.floor(absoluteValue); | |
double seconds = (absoluteValue - min) * 60; | |
DecimalFormat twoDForm = new DecimalFormat("#.##"); | |
seconds = Double.valueOf(twoDForm.format(seconds)); | |
return deg + " " + min + "' " + seconds + "''"; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
public static String parseSpaceLatitude(double value) { | |
String direction = value < 0 ? "S" : "N"; | |
String strValue = parseSpaceLatLonValue(value); | |
return strValue + " " + direction; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
public static String parseSpaceLongitude(double value) { | |
String direction = value < 0 ? "W" : "E"; | |
String strValue = parseSpaceLatLonValue(value); | |
return strValue + " " + direction; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
public static String parseLatitude(double value) { | |
String direction = value < 0 ? "S" : "N"; | |
String strValue = parseLatLonValue(value); | |
return strValue + "\"" + direction; | |
} | |
/** | |
* @param value | |
* @return | |
*/ | |
public static String parseLongitude(double value) { | |
String direction = value < 0 ? "W" : "E"; | |
String strValue = parseLatLonValue(value); | |
return strValue + "\"" + direction; | |
} | |
/** | |
* @param lat1 | |
* @param lon1 | |
* @param lat2 | |
* @param lon2 | |
* @param unit | |
* M = Miles K = Kilometer N = NauticalMiles | |
* @return | |
*/ | |
public static double distance(double lat1, double lon1, double lat2, double lon2, char unit) { | |
double theta = lon1 - lon2; | |
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); | |
dist = Math.acos(dist); | |
dist = rad2deg(dist); | |
dist = dist * 60 * 1.1515; | |
if (unit == 'K') { | |
dist = dist * 1.609344; | |
} else if (unit == 'N') { | |
dist = dist * 0.8684; | |
} | |
if (!Double.isNaN(dist) && !Double.isInfinite(dist)) { | |
DecimalFormat twoDForm = new DecimalFormat("#.##"); | |
dist = Double.valueOf(twoDForm.format(dist)); | |
} | |
return (dist); | |
} | |
private static double deg2rad(double deg) { | |
return (deg * Math.PI / 180.0); | |
} | |
private static double rad2deg(double rad) { | |
return (rad * 180.0 / Math.PI); | |
} | |
/** | |
* @param lat1 | |
* @param lon1 | |
* @param lat2 | |
* @param lon2 | |
* @return | |
*/ | |
public static double[] midPoint(double lat1, double lon1, double lat2, double lon2) { | |
double dLon = Math.toRadians(lon2 - lon1); | |
lat1 = Math.toRadians(lat1); | |
lat2 = Math.toRadians(lat2); | |
lon1 = Math.toRadians(lon1); | |
double Bx = Math.cos(lat2) * Math.cos(dLon); | |
double By = Math.cos(lat2) * Math.sin(dLon); | |
double latitudeMidPoint = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By)); | |
double longitudeMidPoint = lon1 + Math.atan2(By, Math.cos(lat1) + Bx); | |
return new double[] { Math.toDegrees(longitudeMidPoint), Math.toDegrees(latitudeMidPoint) }; | |
} | |
/** | |
* @param lat1 | |
* @param lon1 | |
* @param lat2 | |
* @param lon2 | |
* @return | |
*/ | |
public static double[] midPoint(String lat1, String lon1, String lat2, String lon2) { | |
double lat11 = ParseLatLonValue(lat1); | |
double lon11 = ParseLatLonValue(lon1); | |
// | |
double lat22 = ParseLatLonValue(lat2); | |
double lon22 = ParseLatLonValue(lon2); | |
return midPoint(lat11, lon11, lat22, lon22); | |
} | |
/** | |
* NOT TESTED YET | |
* @param lat1 | |
* @param lon1 | |
* @param lat2 | |
* @param lon2 | |
* @return | |
*/ | |
public static double bearing(double lat1, double lon1, double lat2, double lon2) { | |
// | |
double longitude1 = lon1; | |
double longitude2 = lon2; | |
double latitude1 = Math.toRadians(lat1); | |
double latitude2 = Math.toRadians(lat2); | |
double longDiff = Math.toRadians(longitude2 - longitude1); | |
double y = Math.sin(longDiff) * Math.cos(latitude2); | |
double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff); | |
return (Math.toDegrees(Math.atan2(y, x)) + 360) % 360; | |
} | |
/** | |
* @param longitude1 | |
* @param longitude2 | |
* @return if first Point is on west side of 2nd point | |
*/ | |
public static boolean isWest(double longitude1, double longitude2) { | |
return longitude1 < longitude2; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment