/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.core.model;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* A utility class to convert, parse and validate geographical coordinates.
*/
public final class CoordinatesUtil {
/**
* Maximum possible latitude coordinate.
*/
public static final double LATITUDE_MAX = 90;
/**
* Minimum possible latitude coordinate.
*/
public static final double LATITUDE_MIN = -LATITUDE_MAX;
/**
* Maximum possible longitude coordinate.
*/
public static final double LONGITUDE_MAX = 180;
/**
* Minimum possible longitude coordinate.
*/
public static final double LONGITUDE_MIN = -LONGITUDE_MAX;
/**
* Conversion factor from degrees to microdegrees.
*/
private static final double CONVERSION_FACTOR = 1000000.0;
private static final String DELIMITER = ",";
/**
* Converts a coordinate from degrees to microdegrees (degrees * 10^6). No validation is performed.
*
* @param coordinate
* the coordinate in degrees.
* @return the coordinate in microdegrees (degrees * 10^6).
*/
public static int degreesToMicrodegrees(double coordinate) {
return (int) (coordinate * CONVERSION_FACTOR);
}
/**
* Converts a coordinate from microdegrees (degrees * 10^6) to degrees. No validation is performed.
*
* @param coordinate
* the coordinate in microdegrees (degrees * 10^6).
* @return the coordinate in degrees.
*/
public static double microdegreesToDegrees(int coordinate) {
return coordinate / CONVERSION_FACTOR;
}
/**
* Parses a given number of comma-separated coordinate values from the supplied string.
*
* @param coordinatesString
* a comma-separated string of coordinate values.
* @param numberOfCoordinates
* the expected number of coordinate values in the string.
* @return the coordinate values in the order they have been parsed from the string.
* @throws IllegalArgumentException
* if the string is invalid or does not contain the given number of coordinate values.
*/
public static double[] parseCoordinateString(String coordinatesString, int numberOfCoordinates) {
StringTokenizer stringTokenizer = new StringTokenizer(coordinatesString, DELIMITER, true);
boolean isDelimiter = true;
List<String> tokens = new ArrayList<String>(numberOfCoordinates);
while (stringTokenizer.hasMoreTokens()) {
String token = stringTokenizer.nextToken();
isDelimiter = !isDelimiter;
if (isDelimiter) {
continue;
}
tokens.add(token);
}
if (isDelimiter) {
throw new IllegalArgumentException("invalid coordinate delimiter: " + coordinatesString);
} else if (tokens.size() != numberOfCoordinates) {
throw new IllegalArgumentException("invalid number of coordinate values: " + coordinatesString);
}
double[] coordinates = new double[numberOfCoordinates];
for (int i = 0; i < numberOfCoordinates; ++i) {
coordinates[i] = Double.parseDouble(tokens.get(i));
}
return coordinates;
}
/**
* @param latitude
* the latitude coordinate in degrees which should be validated.
* @throws IllegalArgumentException
* if the latitude coordinate is invalid or {@link Double#NaN}.
*/
public static void validateLatitude(double latitude) {
if (Double.isNaN(latitude) || latitude < LATITUDE_MIN || latitude > LATITUDE_MAX) {
throw new IllegalArgumentException("invalid latitude: " + latitude);
}
}
/**
* @param longitude
* the longitude coordinate in degrees which should be validated.
* @throws IllegalArgumentException
* if the longitude coordinate is invalid or {@link Double#NaN}.
*/
public static void validateLongitude(double longitude) {
if (Double.isNaN(longitude) || longitude < LONGITUDE_MIN || longitude > LONGITUDE_MAX) {
throw new IllegalArgumentException("invalid longitude: " + longitude);
}
}
private CoordinatesUtil() {
throw new IllegalStateException();
}
}