/* * * This file is part of RouteConverter. * * RouteConverter is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * RouteConverter 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RouteConverter; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Copyright (C) 2007 Christian Pesch. All Rights Reserved. * / */ package slash.navigation.common; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.lang.Math.*; import static java.lang.String.format; import static java.util.Locale.ENGLISH; import static slash.common.io.Transfer.parseDouble; import static slash.common.io.Transfer.roundFraction; import static slash.navigation.common.NavigationConversion.formatDouble; import static slash.navigation.common.Orientation.*; /** * Provides unit conversion functionality. * * @author Christian Pesch */ public class UnitConversion { private UnitConversion() { } private static final double METER_OF_A_FEET = 0.3048; private static final double KILOMETER_OF_A_NAUTIC_MILE = 1.8520043; private static final double KILOMETER_OF_A_STATUTE_MILE = 1.609344; public static final double METERS_OF_A_KILOMETER = 1000.0; private static final int SECONDS_OF_A_MINUTE = 60; public static final int SECONDS_OF_AN_HOUR = 60 * SECONDS_OF_A_MINUTE; public static Double nmea2degrees(ValueAndOrientation nmea) { if(nmea == null) return null; double decimal = nmea.getValue() / 100.0; int asInt = (int) decimal; double behindDot = ((decimal - asInt) * 100.0) / SECONDS_OF_A_MINUTE; double degrees = asInt + behindDot; degrees = roundFraction(degrees, 10); Orientation orientation = nmea.getOrientation(); boolean southOrWest = orientation.equals(South) || orientation.equals(West); return southOrWest ? -degrees : degrees; } private static ValueAndOrientation position2nmea(Double degrees, Orientation aboveZero, Orientation belowZero) { if(degrees == null) return null; int asInt = (int) degrees.doubleValue(); double behindDot = degrees - asInt; double behindDdMm = behindDot * SECONDS_OF_A_MINUTE; double ddmm = asInt * 100.0 + behindDdMm; double longitude = abs(ddmm); longitude = roundFraction(longitude, 10); Orientation eastOrWest = ddmm >= 0.0 ? aboveZero : belowZero; return new ValueAndOrientation(longitude, eastOrWest); } public static ValueAndOrientation longitude2nmea(Double longitude) { return position2nmea(longitude, East, West); } public static ValueAndOrientation latitude2nmea(Double latitude) { return position2nmea(latitude, North, South); } private static String coordinate2ddmm(double coordinate, Orientation positive, Orientation negative) { double absolute = abs(coordinate); double dd = floor(absolute); double mm = (absolute - dd) * SECONDS_OF_A_MINUTE; return format(ENGLISH, "%s %.0f\u00B0 %.3f'", coordinate >= 0.0 ? positive.value() : negative.value(), dd, mm); } public static String longitude2ddmm(double longitude) { return coordinate2ddmm(longitude, East, West); } public static String latitude2ddmm(double latitude) { return coordinate2ddmm(latitude, North, South); } private static final Pattern DDMM_TO_COORDINATE = Pattern. compile("\\s*(\\w)\\s*" + "([\\d\\.]*)\\s*\u00B0\\s*" + "([\\d\\.]*)\\s*'\\s*"); private static Double ddmm2coordinate(String coordinateAsDdmm, Orientation negative) { if(coordinateAsDdmm != null) { Matcher matcher = DDMM_TO_COORDINATE.matcher(coordinateAsDdmm); if (matcher.matches()) { Orientation orientation = Orientation.fromValue(matcher.group(1)); Double degree = parseDouble(matcher.group(2)); Double minutes = parseDouble(matcher.group(3)); if(degree != null && minutes != null) { double coordinate = degree + (minutes / SECONDS_OF_A_MINUTE); if (orientation != null && orientation.equals(negative)) coordinate = -coordinate; return formatDouble(coordinate, 7); } } } return null; } public static Double ddmm2longitude(String longitude) { return ddmm2coordinate(longitude, West); } public static double ddmm2latitude(String latitude) { return ddmm2coordinate(latitude, South); } private static String coordinate2ddmmss(double coordinate, Orientation positive, Orientation negative) { double absolute = abs(coordinate); double dd = floor(absolute); double minutes = (absolute - dd) * SECONDS_OF_A_MINUTE; double mm = floor(minutes); double sss = (minutes - mm) * SECONDS_OF_A_MINUTE; if (rint(sss) == SECONDS_OF_A_MINUTE) { mm++; sss = 0; } if (rint(mm) == SECONDS_OF_A_MINUTE) { dd++; mm = 0; } return format(ENGLISH, "%s %.0f\u00B0 %.0f' %.3f\"", coordinate >= 0.0 ? positive.value() : negative.value(), dd, mm, sss); } public static String longitude2ddmmss(double longitude) { return coordinate2ddmmss(longitude, East, West); } public static String latitude2ddmmss(double latitude) { return coordinate2ddmmss(latitude, North, South); } private static final Pattern DDMMSS_TO_COORDINATE = Pattern. compile("\\s*(\\w)\\s*" + "([\\d\\.]*)\\s*\u00B0\\s*" + "([\\d\\.]*)\\s*'\\s*" + "([\\d\\.]*)\\s*\"\\s*"); private static Double ddmmss2coordinate(String coordinateAsDdmmss, Orientation negative) { if(coordinateAsDdmmss != null) { Matcher matcher = DDMMSS_TO_COORDINATE.matcher(coordinateAsDdmmss); if (matcher.matches()) { Orientation orientation = Orientation.fromValue(matcher.group(1)); Double degree = parseDouble(matcher.group(2)); Double minutes = parseDouble(matcher.group(3)); Double seconds = parseDouble(matcher.group(4)); if(degree != null && minutes != null && seconds != null) { double coordinate = degree + (minutes / SECONDS_OF_A_MINUTE) + (seconds / SECONDS_OF_AN_HOUR); if (orientation != null && orientation.equals(negative)) coordinate = -coordinate; return formatDouble(coordinate, 7); } } } return null; } public static Double ddmmss2longitude(String longitude) { return ddmmss2coordinate(longitude, West); } public static Double ddmmss2latitude(String latitude) { return ddmmss2coordinate(latitude, South); } public static double feetToMeters(double feet) { return feet * METER_OF_A_FEET; } public static double meterToFeets(double meter) { return meter / METER_OF_A_FEET; } public static double nauticMilesToKiloMeter(double miles) { return miles * KILOMETER_OF_A_NAUTIC_MILE; } public static double kiloMeterToNauticMiles(double kiloMeter) { return kiloMeter / KILOMETER_OF_A_NAUTIC_MILE; } public static double statuteMilesToKiloMeter(double miles) { return miles * KILOMETER_OF_A_STATUTE_MILE; } public static double kiloMeterToStatuteMiles(double kiloMeter) { return kiloMeter / KILOMETER_OF_A_STATUTE_MILE; } public static double msToKmh(double metersPerSecond) { return metersPerSecond * SECONDS_OF_AN_HOUR / METERS_OF_A_KILOMETER; } public static double kmhToMs(double kiloMetersPerHour) { return kiloMetersPerHour * METERS_OF_A_KILOMETER / SECONDS_OF_AN_HOUR; } }