diff --git a/src/gov/nasa/worldwind/geom/LatLon.java b/src/gov/nasa/worldwind/geom/LatLon.java
index 723e3aa90d..cbcf64ca7d 100644
--- a/src/gov/nasa/worldwind/geom/LatLon.java
+++ b/src/gov/nasa/worldwind/geom/LatLon.java
@@ -10,6 +10,7 @@
import gov.nasa.worldwind.util.*;
import java.util.*;
+import java.util.regex.*;
/**
* Represents a point on the two-dimensional surface of a globe. Latitude is the degrees North and ranges between [-90,
@@ -23,6 +24,20 @@
public class LatLon
{
public static final LatLon ZERO = new LatLon(Angle.ZERO, Angle.ZERO);
+
+ private static final String SEPARATORS = "(\\s*|,|,\\s*)";
+
+ public static final Pattern DECIMAL_PATTERN = Pattern.compile(
+ "([-|\\+]?\\d+?(\\.\\d+?)??\\s*[N|n|S|s]??)" +
+ SEPARATORS +
+ "([-|\\+]?\\d+?(\\.\\d+?)??\\s*[E|e|W|w]??)");
+
+ public static final Pattern DMS_PATTERN = Pattern.compile(
+ "([-|\\+]?\\d{1,3}[d|D|\u00B0|\\s](\\s*\\d{1,2}['|\u2019|\\s])?(\\s*\\d{1,2}(\\.\\d+?)??[\"|\u201d])?\\s*[N|n|S|s]?)" +
+ SEPARATORS +
+ "([-|\\+]?\\d{1,3}[d|D|\u00B0|\\s](\\s*\\d{1,2}['|\u2019|\\s])?(\\s*\\d{1,2}(\\.\\d+?)??[\"|\u201d])?\\s*[E|e|W|w]?)");
+
+ public static final Pattern PATTERN = Pattern.compile(DECIMAL_PATTERN.pattern() + "|" + DMS_PATTERN.pattern());
/**
* A near zero threshold used in some of the rhumb line calculations where floating point calculations cause
@@ -1640,15 +1655,14 @@ public static LatLon intersectionWithMeridian(LatLon p1, LatLon p2, Angle meridi
* Parses a string containing latitude and longitude coordinates in either Degrees-minutes-seconds or decimal
* degrees. The latitude must precede the longitude and the angles must be separated by a comma.
*
- * @param latLonString a string containing the comma separated latitude and longitude in either DMS or decimal
- * degrees.
+ * @param latLonString a string containing the comma separated latitude and longitude in either DMS or decimal degrees.
*
* @return a LatLon
instance with the parsed angles.
*
* @throws IllegalArgumentException if latLonString
is null.
* @throws NumberFormatException if the string does not form a latitude, longitude pair.
*/
- public LatLon parseLatLon(String latLonString) // TODO
+ public static LatLon parseLatLon(String latLonString)
{
if (latLonString == null)
{
@@ -1657,7 +1671,70 @@ public LatLon parseLatLon(String latLonString) // TODO
throw new IllegalArgumentException(msg);
}
- throw new UnsupportedOperationException(); // TODO: remove when implemented
+ Angle lat = null;
+ Angle lon = null;
+ latLonString = latLonString.trim();
+
+ // Try to extract a pair of signed decimal values separated by a space, ',' or ', '
+ // Allow E, W, S, N sufixes
+ Matcher matcher = DECIMAL_PATTERN.matcher(latLonString);
+ if (matcher.matches())
+ {
+ String sLat = matcher.group(1).trim(); // Latitude
+ int signLat = 1;
+ char suffix = sLat.toUpperCase().charAt(sLat.length() - 1);
+ if (!Character.isDigit(suffix))
+ {
+ signLat = suffix == 'N' ? 1 : -1;
+ sLat = sLat.substring(0, sLat.length() - 1);
+ sLat = sLat.trim();
+ }
+
+ String sLon = matcher.group(4).trim(); // Longitude
+ int signLon = 1;
+ suffix = sLon.toUpperCase().charAt(sLon.length() - 1);
+ if (!Character.isDigit(suffix))
+ {
+ signLon = suffix == 'E' ? 1 : -1;
+ sLon = sLon.substring(0, sLon.length() - 1);
+ sLon = sLon.trim();
+ }
+
+ lat = Angle.fromDegrees(Double.parseDouble(sLat) * signLat);
+ lon = Angle.fromDegrees(Double.parseDouble(sLon) * signLon);
+ }
+
+ // Try to extract two degrees minute seconds blocks separated by a space, ',' or ', '
+ // Allow S, N, W, E suffixes and signs.
+ // eg: -123° 34' 42" +45° 12' 30"
+ // eg: 123° 34' 42"S 45° 12' 30"W
+ if (lat == null || lon == null)
+ {
+ matcher = DMS_PATTERN.matcher(latLonString);
+ if (matcher.matches())
+ {
+ lat = Angle.fromDMS(matcher.group(1));
+ lon = Angle.fromDMS(matcher.group(6));
+ }
+ }
+
+ if (lat == null || lon == null)
+ {
+ String message = Logging.getMessage("generic.ArgumentOutOfRange", latLonString);
+ Logging.logger().severe(message);
+ throw new IllegalArgumentException(message);
+ }
+
+ if(lat.degrees >= -90 && lat.degrees <= 90 && lon.degrees >= -180 && lon.degrees <= 180)
+ {
+ return new LatLon(lat, lon);
+ }
+ else
+ {
+ String message = Logging.getMessage("generic.ArgumentOutOfRange", latLonString);
+ Logging.logger().severe(message);
+ throw new IllegalArgumentException(message);
+ }
}
@Override
diff --git a/src/gov/nasa/worldwindx/examples/GoToCoordinatePanel.java b/src/gov/nasa/worldwindx/examples/GoToCoordinatePanel.java
index ce15a11596..5fdd7b0f5b 100644
--- a/src/gov/nasa/worldwindx/examples/GoToCoordinatePanel.java
+++ b/src/gov/nasa/worldwindx/examples/GoToCoordinatePanel.java
@@ -72,7 +72,16 @@ private JPanel makePanel()
{
public void actionPerformed(ActionEvent event)
{
- LatLon latLon = computeLatLonFromString(coordInput.getText(), wwd.getModel().getGlobe());
+ LatLon latLon = null;
+ try
+ {
+ MGRSCoord coordinate = MGRSCoord.fromString(coordInput.getText(), wwd.getModel().getGlobe());
+ latLon = new LatLon(coordinate.getLatitude(), coordinate.getLongitude());
+ }
+ catch (Exception e)
+ {
+ latLon = LatLon.parseLatLon(coordInput.getText());
+ }
updateResult(latLon);
}
});
@@ -92,7 +101,16 @@ public void actionPerformed(ActionEvent event)
{
public void actionPerformed(ActionEvent event)
{
- LatLon latLon = computeLatLonFromString(coordInput.getText(), wwd.getModel().getGlobe());
+ LatLon latLon = null;
+ try
+ {
+ MGRSCoord coordinate = MGRSCoord.fromString(coordInput.getText(), wwd.getModel().getGlobe());
+ latLon = new LatLon(coordinate.getLatitude(), coordinate.getLongitude());
+ }
+ catch (Exception e)
+ {
+ latLon = LatLon.parseLatLon(coordInput.getText());
+ }
updateResult(latLon);
if (latLon != null)
{
@@ -125,156 +143,4 @@ private void updateResult(LatLon latLon)
resultLabel.setText("Invalid coordinates");
}
-
- /**
- * Tries to extract a latitude and a longitude from the given text string.
- *
- * @param coordString the input string.
- * @param globe the current Globe
.
- * @return the corresponding LatLon
or null
.
- */
- private static LatLon computeLatLonFromString(String coordString, Globe globe)
- {
- if (coordString == null)
- {
- String msg = Logging.getMessage("nullValue.StringIsNull");
- Logging.logger().severe(msg);
- throw new IllegalArgumentException(msg);
- }
-
- Angle lat = null;
- Angle lon = null;
- coordString = coordString.trim();
- String regex;
- String separators = "(\\s*|,|,\\s*)";
- Pattern pattern;
- Matcher matcher;
-
- // Try MGRS - allow spaces
- regex = "\\d{1,2}[A-Za-z]\\s*[A-Za-z]{2}\\s*\\d{1,5}\\s*\\d{1,5}";
- if (coordString.matches(regex))
- {
- try
- {
- MGRSCoord MGRS = MGRSCoord.fromString(coordString, globe);
- // NOTE: the MGRSCoord does not always report errors with invalide strings,
- // but will have lat and lon set to zero
- if (MGRS.getLatitude().degrees != 0 || MGRS.getLatitude().degrees != 0)
- {
- lat = MGRS.getLatitude();
- lon = MGRS.getLongitude();
- }
- else
- return null;
- }
- catch (IllegalArgumentException e)
- {
- return null;
- }
- }
-
- // Try to extract a pair of signed decimal values separated by a space, ',' or ', '
- // Allow E, W, S, N sufixes
- if (lat == null || lon == null)
- {
- regex = "([-|\\+]?\\d+?(\\.\\d+?)??\\s*[N|n|S|s]??)";
- regex += separators;
- regex += "([-|\\+]?\\d+?(\\.\\d+?)??\\s*[E|e|W|w]??)";
- pattern = Pattern.compile(regex);
- matcher = pattern.matcher(coordString);
- if (matcher.matches())
- {
- String sLat = matcher.group(1).trim(); // Latitude
- int signLat = 1;
- char suffix = sLat.toUpperCase().charAt(sLat.length() - 1);
- if (!Character.isDigit(suffix))
- {
- signLat = suffix == 'N' ? 1 : -1;
- sLat = sLat.substring(0, sLat.length() - 1);
- sLat = sLat.trim();
- }
-
- String sLon = matcher.group(4).trim(); // Longitude
- int signLon = 1;
- suffix = sLon.toUpperCase().charAt(sLon.length() - 1);
- if (!Character.isDigit(suffix))
- {
- signLon = suffix == 'E' ? 1 : -1;
- sLon = sLon.substring(0, sLon.length() - 1);
- sLon = sLon.trim();
- }
-
- lat = Angle.fromDegrees(Double.parseDouble(sLat) * signLat);
- lon = Angle.fromDegrees(Double.parseDouble(sLon) * signLon);
- }
- }
-
- // Try to extract two degrees minute seconds blocks separated by a space, ',' or ', '
- // Allow S, N, W, E suffixes and signs.
- // eg: -123� 34' 42" +45� 12' 30"
- // eg: 123� 34' 42"S 45� 12' 30"W
- if (lat == null || lon == null)
- {
- regex = "([-|\\+]?\\d{1,3}[d|D|\u00B0|\\s](\\s*\\d{1,2}['|\u2019|\\s])?(\\s*\\d{1,2}[\"|\u201d])?\\s*[N|n|S|s]?)";
- regex += separators;
- regex += "([-|\\+]?\\d{1,3}[d|D|\u00B0|\\s](\\s*\\d{1,2}['|\u2019|\\s])?(\\s*\\d{1,2}[\"|\u201d])?\\s*[E|e|W|w]?)";
- pattern = Pattern.compile(regex);
- matcher = pattern.matcher(coordString);
- if (matcher.matches())
- {
- lat = parseDMSString(matcher.group(1));
- lon = parseDMSString(matcher.group(5));
- }
- }
-
- if (lat == null || lon == null)
- return null;
-
- if(lat.degrees >= -90 && lat.degrees <= 90 && lon.degrees >= -180 && lon.degrees <= 180)
- return new LatLon(lat, lon);
-
- return null;
- }
-
- /**
- * Parse a Degrees, Minute, Second coordinate string.
- *
- * @param dmsString the string to parse.
- * @return the corresponding Angle
or null.
- */
- private static Angle parseDMSString(String dmsString)
- {
- // Replace degree, min and sec signs with space
- dmsString = dmsString.replaceAll("[D|d|\u00B0|'|\u2019|\"|\u201d]", " ");
- // Replace multiple spaces with single ones
- dmsString = dmsString.replaceAll("\\s+", " ");
- dmsString = dmsString.trim();
-
- // Check for sign prefix and suffix
- int sign = 1;
- char suffix = dmsString.toUpperCase().charAt(dmsString.length() - 1);
- if (!Character.isDigit(suffix))
- {
- sign = (suffix == 'N' || suffix == 'E') ? 1 : -1;
- dmsString = dmsString.substring(0, dmsString.length() - 1);
- dmsString = dmsString.trim();
- }
- char prefix = dmsString.charAt(0);
- if (!Character.isDigit(prefix))
- {
- sign *= (prefix == '-') ? -1 : 1;
- dmsString = dmsString.substring(1, dmsString.length());
- }
-
- // Process degrees, minutes and seconds
- String[] DMS = dmsString.split(" ");
- double d = Integer.parseInt(DMS[0]);
- double m = DMS.length > 1 ? Integer.parseInt(DMS[1]) : 0;
- double s = DMS.length > 2 ? Integer.parseInt(DMS[2]) : 0;
-
- if (m >= 0 && m <= 60 && s >= 0 && s <= 60)
- return Angle.fromDegrees(d * sign + m / 60 * sign + s / 3600 * sign);
-
- return null;
- }
}