UnitsConverter.java
/*
* Licensed to GIScience Research Group, Heidelberg University (GIScience)
*
* http://www.giscience.uni-hd.de
* http://www.heigit.org
*
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The GIScience licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.heigit.ors.util;
public class UnitsConverter {
private UnitsConverter() {
}
public static double sqMetersToSqMiles(double value) {
return value * 3.86102e-7;
}
public static double sqMetersToSqKilometers(double value) {
return value * 1e-6;
}
public static double metersToKilometers(double value) {
return value * 0.001;
}
public static double metersToMiles(double value) {
return value * 0.000621371;
}
/**
* Convert a OSM width value to a decimal value in metres. In osm the width could be stored in many different units
* and so this method attempts to convert them all to metres.
*
* @param unprocessedLinearValue The obtained width tag value
* @return The width value converted to metres
*/
public static double convertOSMDistanceTagToMeters(String unprocessedLinearValue) {
double processedLinearValue = -1d;
// Valid values are:
/*
processedLinearValue=x (default metres)
processedLinearValue=x m (metre)
processedLinearValue=x km (kilometre)
processedLinearValue=x mi (mile)
processedLinearValue=x nmi (nautical mile)
processedLinearValue=x'y" (feet and inches)
However, many people omit the space, even though they shouldn't
*/
if (unprocessedLinearValue.contains(" ")) {
// we are working with a specified unit
String[] split = unprocessedLinearValue.split(" ");
if (split.length == 2) {
try {
processedLinearValue = Double.parseDouble(split[0]);
switch (split[1]) {
case "m":
// do nothing as already in metres
break;
case "km":
processedLinearValue = processedLinearValue / 0.001;
break;
case "cm":
processedLinearValue = processedLinearValue / 100.0;
break;
case "mi":
processedLinearValue = processedLinearValue / 0.000621371;
break;
case "nmi":
processedLinearValue = processedLinearValue / 0.000539957;
break;
default:
// Invalid unit
processedLinearValue = -1d;
}
} catch (Exception e) {
processedLinearValue = -1d;
}
}
} else if (unprocessedLinearValue.contains("'") && unprocessedLinearValue.contains("\"")) {
// Working with feet and inches
String[] split = unprocessedLinearValue.split("'");
if (split.length == 2) {
split[1] = split[1].replace("\"", "");
try {
processedLinearValue = Double.parseDouble(split[0]) * 12d; // 12 inches to a foot
processedLinearValue += Double.parseDouble(split[1]);
// convert to metres
processedLinearValue = processedLinearValue * 0.0254;
} catch (Exception e) {
processedLinearValue = -1d;
}
}
} else {
// Try and read a number and assume it is in metres
try {
processedLinearValue = Double.parseDouble(unprocessedLinearValue);
} catch (Exception e) {
processedLinearValue = -1d;
}
}
// If the processedLinearValue is still -1, then it could be that they have used an invalid tag, so just try and parse the most common mistakes
if (processedLinearValue == -1d) {
// Be careful of the order as 3cm ends in both cm and m, so we should check for cm first
try {
if (unprocessedLinearValue.endsWith("cm")) {
String[] split = unprocessedLinearValue.split("cm");
if (split.length == 2) {
processedLinearValue = Double.parseDouble(split[0]) / 100f;
}
} else if (unprocessedLinearValue.endsWith("km")) {
String[] split = unprocessedLinearValue.split("km");
if (split.length == 2) {
processedLinearValue = Double.parseDouble(split[0]) / 0.001f;
}
} else if (unprocessedLinearValue.endsWith("nmi")) {
String[] split = unprocessedLinearValue.split("nmi");
if (split.length == 2) {
processedLinearValue = Double.parseDouble(split[0]) / 0.000539957;
}
} else if (unprocessedLinearValue.endsWith("mi")) {
String[] split = unprocessedLinearValue.split("mi");
if (split.length == 2) {
processedLinearValue = Double.parseDouble(split[0]) / 0.000621371;
}
} else if (unprocessedLinearValue.endsWith("m")) {
String[] split = unprocessedLinearValue.split("m");
if (split.length == 2) {
processedLinearValue = Double.parseDouble(split[0]);
}
}
} catch (NumberFormatException nfe) {
// There was an invalid number, so just set it to be the "invalid" value
processedLinearValue = -1d;
}
}
// If the value is more than three, we need more bits in the encoder to store it, so we can just cap to 3
if (processedLinearValue > 3)
processedLinearValue = 3;
return processedLinearValue;
}
/**
* Convert the String representation of an incline into a %age incline value. in OSM the tag value could already
* be a %age value, or it could be written as "up", "down", "steep" etc. in which case an incline value is assumed
*
* @param unprocessedInclineValue The value obtained from the incline tag
* @param declineToIncline If true, always return a positive value, otherwise decline slopes are returned as negative values
* @return a percentage incline value
*/
public static int convertOSMInclineValueToPercentage(String unprocessedInclineValue, boolean declineToIncline) {
if (unprocessedInclineValue != null) {
double v = 0d;
boolean isDegree = false;
try {
unprocessedInclineValue = unprocessedInclineValue.replace("%", "");
unprocessedInclineValue = unprocessedInclineValue.replace(",", ".");
if (unprocessedInclineValue.contains("°")) {
unprocessedInclineValue = unprocessedInclineValue.replace("°", "");
isDegree = true;
}
// Replace textual descriptions with assumed values
unprocessedInclineValue = unprocessedInclineValue.replace("up", "10");
unprocessedInclineValue = unprocessedInclineValue.replace("down", "-10");
unprocessedInclineValue = unprocessedInclineValue.replace("yes", "10");
unprocessedInclineValue = unprocessedInclineValue.replace("steep", "15");
unprocessedInclineValue = unprocessedInclineValue.replace("no", "0");
unprocessedInclineValue = unprocessedInclineValue.replace("+/-0", "0");
v = Double.parseDouble(unprocessedInclineValue);
if (isDegree) {
v = Math.tan(v) * 100;
}
} catch (Exception ex) {
// There was a problem, so return a 0 and assume no incline
v = 0;
}
if (declineToIncline && v < 0) {
v = v * -1.0;
}
return (int) Math.round(v);
}
return 0;
}
}