commit
cefbdff0b7
11 changed files with 752 additions and 11 deletions
|
@ -0,0 +1,532 @@
|
||||||
|
package com.google.openlocationcode;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of open location code. https://github.com/google/open-location-code The
|
||||||
|
* OpenLocationCode class is a wrapper around String value {@code code}, which guarantees that the
|
||||||
|
* value is a valid Open Location Code.
|
||||||
|
*
|
||||||
|
* @author Jiri Semecky
|
||||||
|
*/
|
||||||
|
public final class OpenLocationCode {
|
||||||
|
|
||||||
|
private static final BigDecimal BD_0 = new BigDecimal(0);
|
||||||
|
private static final BigDecimal BD_5 = new BigDecimal(5);
|
||||||
|
private static final BigDecimal BD_4 = new BigDecimal(4);
|
||||||
|
private static final BigDecimal BD_20 = new BigDecimal(20);
|
||||||
|
private static final BigDecimal BD_90 = new BigDecimal(90);
|
||||||
|
private static final BigDecimal BD_180 = new BigDecimal(180);
|
||||||
|
private static final double LATITUDE_PRECISION_8_DIGITS = computeLatitudePrecision(8) / 4;
|
||||||
|
private static final double LATITUDE_PRECISION_6_DIGITS = computeLatitudePrecision(6) / 4;
|
||||||
|
private static final double LATITUDE_PRECISION_4_DIGITS = computeLatitudePrecision(4) / 4;
|
||||||
|
|
||||||
|
private static final char[] ALPHABET = "23456789CFGHJMPQRVWX".toCharArray();
|
||||||
|
private static final Map<Character, Integer> CHARACTER_TO_INDEX = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
int index = 0;
|
||||||
|
for (char character : ALPHABET) {
|
||||||
|
char lowerCaseCharacter = Character.toLowerCase(character);
|
||||||
|
CHARACTER_TO_INDEX.put(character, index);
|
||||||
|
CHARACTER_TO_INDEX.put(lowerCaseCharacter, index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final char SEPARATOR = '+';
|
||||||
|
private static final char SEPARATOR_POSITION = 8;
|
||||||
|
private static final char SUFFIX_PADDING = '0';
|
||||||
|
|
||||||
|
/** Class providing information about area covered by Open Location Code. */
|
||||||
|
public class CodeArea {
|
||||||
|
|
||||||
|
private final BigDecimal southLatitude;
|
||||||
|
private final BigDecimal westLongitude;
|
||||||
|
private final BigDecimal northLatitude;
|
||||||
|
private final BigDecimal eastLongitude;
|
||||||
|
|
||||||
|
public CodeArea(
|
||||||
|
BigDecimal southLatitude,
|
||||||
|
BigDecimal westLongitude,
|
||||||
|
BigDecimal northLatitude,
|
||||||
|
BigDecimal eastLongitude) {
|
||||||
|
this.southLatitude = southLatitude;
|
||||||
|
this.westLongitude = westLongitude;
|
||||||
|
this.northLatitude = northLatitude;
|
||||||
|
this.eastLongitude = eastLongitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSouthLatitude() {
|
||||||
|
return southLatitude.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWestLongitude() {
|
||||||
|
return westLongitude.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitudeHeight() {
|
||||||
|
return northLatitude.subtract(southLatitude).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitudeWidth() {
|
||||||
|
return eastLongitude.subtract(westLongitude).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCenterLatitude() {
|
||||||
|
return southLatitude.add(northLatitude).doubleValue() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCenterLongitude() {
|
||||||
|
return westLongitude.add(eastLongitude).doubleValue() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getNorthLatitude() {
|
||||||
|
return northLatitude.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getEastLongitude() {
|
||||||
|
return eastLongitude.doubleValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** The state of the OpenLocationCode. */
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
/** Creates Open Location Code for the provided code. */
|
||||||
|
public OpenLocationCode(String code) {
|
||||||
|
if (!isValidCode(code)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The provided code '" + code + "' is not a valid Open Location Code.");
|
||||||
|
}
|
||||||
|
this.code = code.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates Open Location Code from the provided latitude, longitude and desired code length. */
|
||||||
|
public OpenLocationCode(double latitude, double longitude, int codeLength)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (codeLength < 4 || (codeLength < 10 & codeLength % 2 == 1)) {
|
||||||
|
throw new IllegalArgumentException("Illegal code length " + codeLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
latitude = clipLatitude(latitude);
|
||||||
|
longitude = normalizeLongitude(longitude);
|
||||||
|
|
||||||
|
// Latitude 90 needs to be adjusted to be just less, so the returned code can also be decoded.
|
||||||
|
if (latitude == 90) {
|
||||||
|
latitude = latitude - 0.9 * computeLatitudePrecision(codeLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder codeBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
// Ensure the latitude and longitude are within [0, 180] and [0, 360) respectively.
|
||||||
|
/* Note: double type can't be used because of the rounding arithmetic due to floating point
|
||||||
|
* implementation. Eg. "8.95 - 8" can give result 0.9499999999999 instead of 0.95 which
|
||||||
|
* incorrectly classify the points on the border of a cell.
|
||||||
|
*/
|
||||||
|
BigDecimal remainingLongitude = new BigDecimal(longitude + 180);
|
||||||
|
BigDecimal remainingLatitude = new BigDecimal(latitude + 90);
|
||||||
|
|
||||||
|
// Create up to 10 significant digits from pairs alternating latitude and longitude.
|
||||||
|
int generatedDigits = 0;
|
||||||
|
|
||||||
|
while (generatedDigits < codeLength) {
|
||||||
|
// Always the integer part of the remaining latitude/longitude will be used for the following
|
||||||
|
// digit.
|
||||||
|
if (generatedDigits == 0) {
|
||||||
|
// First step World division: Map <0..400) to <0..20) for both latitude and longitude.
|
||||||
|
remainingLatitude = remainingLatitude.divide(BD_20);
|
||||||
|
remainingLongitude = remainingLongitude.divide(BD_20);
|
||||||
|
} else if (generatedDigits < 10) {
|
||||||
|
remainingLatitude = remainingLatitude.multiply(BD_20);
|
||||||
|
remainingLongitude = remainingLongitude.multiply(BD_20);
|
||||||
|
} else {
|
||||||
|
remainingLatitude = remainingLatitude.multiply(BD_5);
|
||||||
|
remainingLongitude = remainingLongitude.multiply(BD_4);
|
||||||
|
}
|
||||||
|
int latitudeDigit = remainingLatitude.intValue();
|
||||||
|
int longitudeDigit = remainingLongitude.intValue();
|
||||||
|
if (generatedDigits < 10) {
|
||||||
|
codeBuilder.append(ALPHABET[latitudeDigit]);
|
||||||
|
codeBuilder.append(ALPHABET[longitudeDigit]);
|
||||||
|
generatedDigits += 2;
|
||||||
|
} else {
|
||||||
|
codeBuilder.append(ALPHABET[4 * latitudeDigit + longitudeDigit]);
|
||||||
|
generatedDigits += 1;
|
||||||
|
}
|
||||||
|
remainingLatitude = remainingLatitude.subtract(new BigDecimal(latitudeDigit));
|
||||||
|
remainingLongitude = remainingLongitude.subtract(new BigDecimal(longitudeDigit));
|
||||||
|
if (generatedDigits == SEPARATOR_POSITION) {
|
||||||
|
codeBuilder.append(SEPARATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (generatedDigits < SEPARATOR_POSITION) {
|
||||||
|
for (; generatedDigits < SEPARATOR_POSITION; generatedDigits++) {
|
||||||
|
codeBuilder.append(SUFFIX_PADDING);
|
||||||
|
}
|
||||||
|
codeBuilder.append(SEPARATOR);
|
||||||
|
}
|
||||||
|
this.code = codeBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates Open Location Code with code length 10 from the provided latitude, longitude. */
|
||||||
|
public OpenLocationCode(double latitude, double longitude) {
|
||||||
|
this(latitude, longitude, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes latitude/longitude into 10 digit Open Location Code. This method is equivalent to
|
||||||
|
* creating the OpenLocationCode object and getting the code from it.
|
||||||
|
*/
|
||||||
|
public static String encode(double latitude, double longitude) {
|
||||||
|
return new OpenLocationCode(latitude, longitude).getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes latitude/longitude into Open Location Code of the provided length. This method is
|
||||||
|
* equivalent to creating the OpenLocationCode object and getting the code from it.
|
||||||
|
*/
|
||||||
|
public static String encode(double latitude, double longitude, int codeLength) {
|
||||||
|
return new OpenLocationCode(latitude, longitude, codeLength).getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes {@link OpenLocationCode} object into {@link CodeArea} object encapsulating
|
||||||
|
* latitude/longitude bounding box.
|
||||||
|
*/
|
||||||
|
public CodeArea decode() {
|
||||||
|
if (!isFullCode(code)) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Method decode() could only be called on valid full codes, code was " + code + ".");
|
||||||
|
}
|
||||||
|
String decoded = code.replaceAll("[0+]", "");
|
||||||
|
// Decode the lat/lng pair component.
|
||||||
|
BigDecimal southLatitude = BD_0;
|
||||||
|
BigDecimal westLongitude = BD_0;
|
||||||
|
|
||||||
|
int digit = 0;
|
||||||
|
double latitudeResolution = 400, longitudeResolution = 400;
|
||||||
|
|
||||||
|
// Decode pair.
|
||||||
|
while (digit < decoded.length()) {
|
||||||
|
if (digit < 10) {
|
||||||
|
latitudeResolution /= 20;
|
||||||
|
longitudeResolution /= 20;
|
||||||
|
southLatitude =
|
||||||
|
southLatitude.add(
|
||||||
|
new BigDecimal(latitudeResolution * CHARACTER_TO_INDEX.get(decoded.charAt(digit))));
|
||||||
|
westLongitude =
|
||||||
|
westLongitude.add(
|
||||||
|
new BigDecimal(
|
||||||
|
longitudeResolution * CHARACTER_TO_INDEX.get(decoded.charAt(digit + 1))));
|
||||||
|
digit += 2;
|
||||||
|
} else {
|
||||||
|
latitudeResolution /= 5;
|
||||||
|
longitudeResolution /= 4;
|
||||||
|
southLatitude =
|
||||||
|
southLatitude.add(
|
||||||
|
new BigDecimal(
|
||||||
|
latitudeResolution * (CHARACTER_TO_INDEX.get(decoded.charAt(digit)) / 4)));
|
||||||
|
westLongitude =
|
||||||
|
westLongitude.add(
|
||||||
|
new BigDecimal(
|
||||||
|
longitudeResolution * (CHARACTER_TO_INDEX.get(decoded.charAt(digit)) % 4)));
|
||||||
|
digit += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CodeArea(
|
||||||
|
southLatitude.subtract(BD_90),
|
||||||
|
westLongitude.subtract(BD_180),
|
||||||
|
southLatitude.subtract(BD_90).add(new BigDecimal(latitudeResolution)),
|
||||||
|
westLongitude.subtract(BD_180).add(new BigDecimal(longitudeResolution)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes code representing Open Location Code into {@link CodeArea} object encapsulating
|
||||||
|
* latitude/longitude bounding box.
|
||||||
|
*
|
||||||
|
* @param code Open Location Code to be decoded.
|
||||||
|
* @throws IllegalArgumentException if the provided code is not a valid Open Location Code.
|
||||||
|
*/
|
||||||
|
public static CodeArea decode(String code) throws IllegalArgumentException {
|
||||||
|
return new OpenLocationCode(code).decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether this {@link OpenLocationCode} is a full Open Location Code. */
|
||||||
|
public boolean isFull() {
|
||||||
|
return code.indexOf(SEPARATOR) == SEPARATOR_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether the provided Open Location Code is a full Open Location Code. */
|
||||||
|
public static boolean isFull(String code) throws IllegalArgumentException {
|
||||||
|
return new OpenLocationCode(code).isFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether this {@link OpenLocationCode} is a short Open Location Code. */
|
||||||
|
public boolean isShort() {
|
||||||
|
return code.indexOf(SEPARATOR) >= 0 && code.indexOf(SEPARATOR) < SEPARATOR_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether the provided Open Location Code is a short Open Location Code. */
|
||||||
|
public static boolean isShort(String code) throws IllegalArgumentException {
|
||||||
|
return new OpenLocationCode(code).isShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this {@link OpenLocationCode} is a padded Open Location Code, meaning that it
|
||||||
|
* contains less than 8 valid digits.
|
||||||
|
*/
|
||||||
|
private boolean isPadded() {
|
||||||
|
return code.indexOf(SUFFIX_PADDING) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the provided Open Location Code is a padded Open Location Code, meaning that it
|
||||||
|
* contains less than 8 valid digits.
|
||||||
|
*/
|
||||||
|
public static boolean isPadded(String code) throws IllegalArgumentException {
|
||||||
|
return new OpenLocationCode(code).isPadded();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns short {@link OpenLocationCode} from the full Open Location Code created by removing
|
||||||
|
* four or six digits, depending on the provided reference point. It removes as many digits as
|
||||||
|
* possible.
|
||||||
|
*/
|
||||||
|
public OpenLocationCode shorten(double referenceLatitude, double referenceLongitude) {
|
||||||
|
if (!isFull()) {
|
||||||
|
throw new IllegalStateException("shorten() method could only be called on a full code.");
|
||||||
|
}
|
||||||
|
if (isPadded()) {
|
||||||
|
throw new IllegalStateException("shorten() method can not be called on a padded code.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeArea codeArea = decode();
|
||||||
|
double latitudeDiff = Math.abs(referenceLatitude - codeArea.getCenterLatitude());
|
||||||
|
double longitudeDiff = Math.abs(referenceLongitude - codeArea.getCenterLongitude());
|
||||||
|
|
||||||
|
if (latitudeDiff < LATITUDE_PRECISION_8_DIGITS && longitudeDiff < LATITUDE_PRECISION_8_DIGITS) {
|
||||||
|
return new OpenLocationCode(code.substring(8));
|
||||||
|
}
|
||||||
|
if (latitudeDiff < LATITUDE_PRECISION_6_DIGITS && longitudeDiff < LATITUDE_PRECISION_6_DIGITS) {
|
||||||
|
return new OpenLocationCode(code.substring(6));
|
||||||
|
}
|
||||||
|
if (latitudeDiff < LATITUDE_PRECISION_4_DIGITS && longitudeDiff < LATITUDE_PRECISION_4_DIGITS) {
|
||||||
|
return new OpenLocationCode(code.substring(4));
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Reference location is too far from the Open Location Code center.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an {@link OpenLocationCode} object representing a full Open Location Code from this
|
||||||
|
* (short) Open Location Code, given the reference location.
|
||||||
|
*/
|
||||||
|
public OpenLocationCode recover(double referenceLatitude, double referenceLongitude) {
|
||||||
|
if (isFull()) {
|
||||||
|
// Note: each code is either full xor short, no other option.
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
referenceLatitude = clipLatitude(referenceLatitude);
|
||||||
|
referenceLongitude = normalizeLongitude(referenceLongitude);
|
||||||
|
|
||||||
|
int digitsToRecover = 8 - code.indexOf(SEPARATOR);
|
||||||
|
// The resolution (height and width) of the padded area in degrees.
|
||||||
|
double paddedAreaSize = Math.pow(20, 2 - (digitsToRecover / 2));
|
||||||
|
|
||||||
|
// Use the reference location to pad the supplied short code and decode it.
|
||||||
|
String recoveredPrefix =
|
||||||
|
new OpenLocationCode(referenceLatitude, referenceLongitude)
|
||||||
|
.getCode()
|
||||||
|
.substring(0, digitsToRecover);
|
||||||
|
OpenLocationCode recovered = new OpenLocationCode(recoveredPrefix + code);
|
||||||
|
CodeArea recoveredCodeArea = recovered.decode();
|
||||||
|
double recoveredLatitude = recoveredCodeArea.getCenterLatitude();
|
||||||
|
double recoveredLongitude = recoveredCodeArea.getCenterLongitude();
|
||||||
|
|
||||||
|
// Move the recovered latitude by one resolution up or down if it is too far from the reference.
|
||||||
|
double latitudeDiff = recoveredLatitude - referenceLatitude;
|
||||||
|
if (latitudeDiff > paddedAreaSize / 2) {
|
||||||
|
recoveredLatitude -= paddedAreaSize;
|
||||||
|
} else if (latitudeDiff < -paddedAreaSize / 2) {
|
||||||
|
recoveredLatitude += paddedAreaSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the recovered longitude by one resolution up or down if it is too far from the
|
||||||
|
// reference.
|
||||||
|
double longitudeDiff = recoveredCodeArea.getCenterLongitude() - referenceLongitude;
|
||||||
|
if (longitudeDiff > paddedAreaSize / 2) {
|
||||||
|
recoveredLongitude -= paddedAreaSize;
|
||||||
|
} else if (longitudeDiff < -paddedAreaSize / 2) {
|
||||||
|
recoveredLongitude += paddedAreaSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OpenLocationCode(
|
||||||
|
recoveredLatitude, recoveredLongitude, recovered.getCode().length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the bounding box specified by the Open Location Code contains provided point.
|
||||||
|
*/
|
||||||
|
public boolean contains(double latitude, double longitude) {
|
||||||
|
CodeArea codeArea = decode();
|
||||||
|
return codeArea.getSouthLatitude() <= latitude
|
||||||
|
&& latitude < codeArea.getNorthLatitude()
|
||||||
|
&& codeArea.getWestLongitude() <= longitude
|
||||||
|
&& longitude < codeArea.getEastLongitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OpenLocationCode that = (OpenLocationCode) o;
|
||||||
|
return hashCode() == that.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return code != null ? code.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exposed static helper methods.
|
||||||
|
|
||||||
|
/** Returns whether the provided string is a valid Open Location code. */
|
||||||
|
public static boolean isValidCode(String code) {
|
||||||
|
if (code == null || code.length() < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There must be exactly one separator.
|
||||||
|
int separatorPosition = code.indexOf(SEPARATOR);
|
||||||
|
if (separatorPosition == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (separatorPosition != code.lastIndexOf(SEPARATOR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (separatorPosition % 2 != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check first two characters: only some values from the alphabet are permitted.
|
||||||
|
if (separatorPosition == 8) {
|
||||||
|
// First latitude character can only have first 9 values.
|
||||||
|
Integer index0 = CHARACTER_TO_INDEX.get(code.charAt(0));
|
||||||
|
if (index0 == null || index0 > 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First longitude character can only have first 18 values.
|
||||||
|
Integer index1 = CHARACTER_TO_INDEX.get(code.charAt(1));
|
||||||
|
if (index1 == null || index1 > 17) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the characters before the separator.
|
||||||
|
boolean paddingStarted = false;
|
||||||
|
for (int i = 0; i < separatorPosition; i++) {
|
||||||
|
if (paddingStarted) {
|
||||||
|
// Once padding starts, there must not be anything but padding.
|
||||||
|
if (code.charAt(i) != SUFFIX_PADDING) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CHARACTER_TO_INDEX.keySet().contains(code.charAt(i))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (SUFFIX_PADDING == code.charAt(i)) {
|
||||||
|
paddingStarted = true;
|
||||||
|
// Padding can start on even character: 2, 4 or 6.
|
||||||
|
if (i != 2 && i != 4 && i != 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false; // Illegal character.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the characters after the separator.
|
||||||
|
if (code.length() > separatorPosition + 1) {
|
||||||
|
if (paddingStarted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Only one character after separator is forbidden.
|
||||||
|
if (code.length() == separatorPosition + 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = separatorPosition + 1; i < code.length(); i++) {
|
||||||
|
if (!CHARACTER_TO_INDEX.keySet().contains(code.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns if the code is a valid full Open Location Code. */
|
||||||
|
public static boolean isFullCode(String code) {
|
||||||
|
try {
|
||||||
|
return new OpenLocationCode(code).isFull();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns if the code is a valid short Open Location Code. */
|
||||||
|
public static boolean isShortCode(String code) {
|
||||||
|
try {
|
||||||
|
return new OpenLocationCode(code).isShort();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private static methods.
|
||||||
|
|
||||||
|
private static double clipLatitude(double latitude) {
|
||||||
|
return Math.min(Math.max(latitude, -90), 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double normalizeLongitude(double longitude) {
|
||||||
|
if (longitude < -180) {
|
||||||
|
longitude = (longitude % 360) + 360;
|
||||||
|
}
|
||||||
|
if (longitude >= 180) {
|
||||||
|
longitude = (longitude % 360) - 360;
|
||||||
|
}
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the latitude precision value for a given code length. Lengths <= 10 have the same
|
||||||
|
* precision for latitude and longitude, but lengths > 10 have different precisions due to the
|
||||||
|
* grid method having fewer columns than rows. Copied from the JS implementation.
|
||||||
|
*/
|
||||||
|
private static double computeLatitudePrecision(int codeLength) {
|
||||||
|
if (codeLength <= 10) {
|
||||||
|
return Math.pow(20, Math.floor(codeLength / -2 + 2));
|
||||||
|
}
|
||||||
|
return Math.pow(20, -3) / Math.pow(5, codeLength - 10);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package net.osmand;
|
package net.osmand;
|
||||||
|
|
||||||
|
import com.google.openlocationcode.OpenLocationCode;
|
||||||
|
|
||||||
|
import net.osmand.data.LatLon;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.IllegalFormatException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
@ -14,6 +19,7 @@ public class LocationConvert {
|
||||||
public static final int FORMAT_MINUTES = 1;
|
public static final int FORMAT_MINUTES = 1;
|
||||||
public static final int FORMAT_SECONDS = 2;
|
public static final int FORMAT_SECONDS = 2;
|
||||||
public static final int UTM_FORMAT = 3;
|
public static final int UTM_FORMAT = 3;
|
||||||
|
public static final int OLC_FORMAT = 4;
|
||||||
private static final char DELIM = ':';
|
private static final char DELIM = ':';
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,5 +155,4 @@ public class LocationConvert {
|
||||||
sb.append(df.format(coordinate));
|
sb.append(df.format(coordinate));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.osmand.search.core;
|
package net.osmand.search.core;
|
||||||
|
|
||||||
|
import com.google.openlocationcode.OpenLocationCode;
|
||||||
import com.jwetherell.openmap.common.LatLonPoint;
|
import com.jwetherell.openmap.common.LatLonPoint;
|
||||||
import com.jwetherell.openmap.common.UTMPoint;
|
import com.jwetherell.openmap.common.UTMPoint;
|
||||||
|
|
||||||
|
@ -1031,6 +1032,15 @@ public class SearchCoreFactory {
|
||||||
|
|
||||||
LatLon parseLocation(String s) {
|
LatLon parseLocation(String s) {
|
||||||
s = s.trim();
|
s = s.trim();
|
||||||
|
// detect OLC first
|
||||||
|
// avoid throwing exceptions by carefully checking exceptions
|
||||||
|
if (s.length() > 0 && OpenLocationCode.isValidCode(s)) {
|
||||||
|
OpenLocationCode olc = new OpenLocationCode(s);
|
||||||
|
if (olc.isFull()) {
|
||||||
|
OpenLocationCode.CodeArea codeArea = olc.decode();
|
||||||
|
return new LatLon(codeArea.getCenterLatitude(), codeArea.getCenterLongitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
if(s.length() == 0 || !(s.charAt(0) == '-' || Character.isDigit(s.charAt(0))
|
if(s.length() == 0 || !(s.charAt(0) == '-' || Character.isDigit(s.charAt(0))
|
||||||
|| s.charAt(0) == 'S' || s.charAt(0) == 's'
|
|| s.charAt(0) == 'S' || s.charAt(0) == 's'
|
||||||
|| s.charAt(0) == 'N' || s.charAt(0) == 'n'
|
|| s.charAt(0) == 'N' || s.charAt(0) == 'n'
|
||||||
|
|
|
@ -297,6 +297,74 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/olcLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<android.support.design.widget.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="54dp"
|
||||||
|
android:layout_marginRight="16dp">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/olcEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/navigate_point_olc"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="textCapCharacters|textNoSuggestions"
|
||||||
|
tools:text="6PH57VP3+PQ"/>
|
||||||
|
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/olcClearButton"
|
||||||
|
style="@style/Widget.AppCompat.ActionButton"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:contentDescription="@string/shared_string_clear"
|
||||||
|
android:src="@drawable/ic_action_remove_dark"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/olcInfoLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="54dp"
|
||||||
|
android:layout_marginRight="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/olcInfoTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="OLC area information"
|
||||||
|
android:inputType="textMultiLine"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/formatLayout"
|
android:id="@+id/formatLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -761,6 +761,10 @@
|
||||||
<string name="rendering_attr_transportStops_name">Transport stops</string>
|
<string name="rendering_attr_transportStops_name">Transport stops</string>
|
||||||
|
|
||||||
<string name="navigate_point_zone">Zone</string>
|
<string name="navigate_point_zone">Zone</string>
|
||||||
|
<string name="navigate_point_olc">Open Location Code</string>
|
||||||
|
<string name="navigate_point_olc_info_invalid">Invalid OLC\n</string>
|
||||||
|
<string name="navigate_point_olc_info_short">Short OLC\nPlease provide a full code</string>
|
||||||
|
<string name="navigate_point_olc_info_area">Valid full OLC\nRepresents area: %1$s x %2$s</string>
|
||||||
<string name="navigate_point_northing">Northing</string>
|
<string name="navigate_point_northing">Northing</string>
|
||||||
<string name="navigate_point_easting">Easting</string>
|
<string name="navigate_point_easting">Easting</string>
|
||||||
<string name="download_tab_downloads">All Downloads</string>
|
<string name="download_tab_downloads">All Downloads</string>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.openlocationcode.OpenLocationCode;
|
||||||
import com.jwetherell.openmap.common.LatLonPoint;
|
import com.jwetherell.openmap.common.LatLonPoint;
|
||||||
import com.jwetherell.openmap.common.UTMPoint;
|
import com.jwetherell.openmap.common.UTMPoint;
|
||||||
|
|
||||||
|
@ -156,6 +157,8 @@ public class PointDescription {
|
||||||
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
|
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
|
||||||
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
|
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
|
||||||
+ ((long) pnt.northing);
|
+ ((long) pnt.northing);
|
||||||
|
} else if (f == PointDescription.OLC_FORMAT) {
|
||||||
|
return getLocationOlcName(lat, lon);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return ctx.getString(sh ? R.string.short_location_on_map : R.string.location_on_map, LocationConvert.convert(lat, f),
|
return ctx.getString(sh ? R.string.short_location_on_map : R.string.location_on_map, LocationConvert.convert(lat, f),
|
||||||
|
@ -174,6 +177,8 @@ public class PointDescription {
|
||||||
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
|
UTMPoint pnt = new UTMPoint(new LatLonPoint(lat, lon));
|
||||||
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
|
return pnt.zone_number + "" + pnt.zone_letter + " " + ((long) pnt.easting) + " "
|
||||||
+ ((long) pnt.northing);
|
+ ((long) pnt.northing);
|
||||||
|
} else if (f == PointDescription.OLC_FORMAT) {
|
||||||
|
return getLocationOlcName(lat, lon);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return LocationConvert.convert(lat, f) + ", " + LocationConvert.convert(lon, f);
|
return LocationConvert.convert(lat, f) + ", " + LocationConvert.convert(lon, f);
|
||||||
|
@ -184,6 +189,10 @@ public class PointDescription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getLocationOlcName(double lat, double lon) {
|
||||||
|
return OpenLocationCode.encode(lat, lon);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean contextMenuDisabled() {
|
public boolean contextMenuDisabled() {
|
||||||
return POINT_TYPE_WORLD_REGION_SHOW_ON_MAP.equals(type);
|
return POINT_TYPE_WORLD_REGION_SHOW_ON_MAP.equals(type);
|
||||||
}
|
}
|
||||||
|
@ -338,6 +347,7 @@ public class PointDescription {
|
||||||
public static final int FORMAT_MINUTES = LocationConvert.FORMAT_MINUTES;
|
public static final int FORMAT_MINUTES = LocationConvert.FORMAT_MINUTES;
|
||||||
public static final int FORMAT_SECONDS = LocationConvert.FORMAT_SECONDS;
|
public static final int FORMAT_SECONDS = LocationConvert.FORMAT_SECONDS;
|
||||||
public static final int UTM_FORMAT = LocationConvert.UTM_FORMAT;
|
public static final int UTM_FORMAT = LocationConvert.UTM_FORMAT;
|
||||||
|
public static final int OLC_FORMAT = LocationConvert.OLC_FORMAT;
|
||||||
|
|
||||||
public static String formatToHumanString(Context ctx, int format) {
|
public static String formatToHumanString(Context ctx, int format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
@ -349,6 +359,8 @@ public class PointDescription {
|
||||||
return ctx.getString(R.string.navigate_point_format_DMS);
|
return ctx.getString(R.string.navigate_point_format_DMS);
|
||||||
case LocationConvert.UTM_FORMAT:
|
case LocationConvert.UTM_FORMAT:
|
||||||
return "UTM";
|
return "UTM";
|
||||||
|
case LocationConvert.OLC_FORMAT:
|
||||||
|
return "OLC";
|
||||||
default:
|
default:
|
||||||
return "Unknown format";
|
return "Unknown format";
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,16 +151,18 @@ public class SettingsGeneralActivity extends SettingsBaseActivity implements OnR
|
||||||
}
|
}
|
||||||
registerListPreference(settings.METRIC_SYSTEM, screen, entries, mvls);
|
registerListPreference(settings.METRIC_SYSTEM, screen, entries, mvls);
|
||||||
|
|
||||||
Integer[] cvls = new Integer[4];
|
Integer[] cvls = new Integer[5];
|
||||||
cvls[0] = PointDescription.FORMAT_DEGREES;
|
cvls[0] = PointDescription.FORMAT_DEGREES;
|
||||||
cvls[1] = PointDescription.FORMAT_MINUTES;
|
cvls[1] = PointDescription.FORMAT_MINUTES;
|
||||||
cvls[2] = PointDescription.FORMAT_SECONDS;
|
cvls[2] = PointDescription.FORMAT_SECONDS;
|
||||||
cvls[3] = PointDescription.UTM_FORMAT;
|
cvls[3] = PointDescription.UTM_FORMAT;
|
||||||
entries = new String[4];
|
cvls[4] = PointDescription.OLC_FORMAT;
|
||||||
|
entries = new String[5];
|
||||||
entries[0] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_DEGREES);
|
entries[0] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_DEGREES);
|
||||||
entries[1] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_MINUTES);
|
entries[1] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_MINUTES);
|
||||||
entries[2] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_SECONDS);
|
entries[2] = PointDescription.formatToHumanString(this, PointDescription.FORMAT_SECONDS);
|
||||||
entries[3] = PointDescription.formatToHumanString(this, PointDescription.UTM_FORMAT);
|
entries[3] = PointDescription.formatToHumanString(this, PointDescription.UTM_FORMAT);
|
||||||
|
entries[4] = PointDescription.formatToHumanString(this, PointDescription.OLC_FORMAT);
|
||||||
registerListPreference(settings.COORDINATES_FORMAT, screen, entries, cvls);
|
registerListPreference(settings.COORDINATES_FORMAT, screen, entries, cvls);
|
||||||
|
|
||||||
// See language list and statistics at: https://hosted.weblate.org/projects/osmand/main/
|
// See language list and statistics at: https://hosted.weblate.org/projects/osmand/main/
|
||||||
|
|
|
@ -22,6 +22,7 @@ import net.osmand.plus.GPXUtilities.WptPt;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
import net.osmand.plus.MapMarkersHelper.MapMarker;
|
import net.osmand.plus.MapMarkersHelper.MapMarker;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.OsmandSettings;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
@ -203,8 +204,12 @@ public abstract class MenuController extends BaseMenuController {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addMyLocationToPlainItems(LatLon latLon) {
|
protected void addMyLocationToPlainItems(LatLon latLon) {
|
||||||
|
OsmandSettings st = ((OsmandApplication) getMapActivity().getApplicationContext()).getSettings();
|
||||||
addPlainMenuItem(R.drawable.ic_action_get_my_location, PointDescription.getLocationName(getMapActivity(),
|
addPlainMenuItem(R.drawable.ic_action_get_my_location, PointDescription.getLocationName(getMapActivity(),
|
||||||
latLon.getLatitude(), latLon.getLongitude(), true).replaceAll("\n", " "), false, false, null);
|
latLon.getLatitude(), latLon.getLongitude(), true).replaceAll("\n", " "), false, false, null);
|
||||||
|
if (st.COORDINATES_FORMAT.get() != PointDescription.OLC_FORMAT)
|
||||||
|
addPlainMenuItem(R.drawable.ic_action_get_my_location, PointDescription.getLocationOlcName(
|
||||||
|
latLon.getLatitude(), latLon.getLongitude()).replaceAll("\n", " "), false, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PointDescription getPointDescription() {
|
public PointDescription getPointDescription() {
|
||||||
|
|
|
@ -24,6 +24,8 @@ import net.osmand.data.PointDescription;
|
||||||
import net.osmand.osm.AbstractPoiType;
|
import net.osmand.osm.AbstractPoiType;
|
||||||
import net.osmand.osm.MapPoiTypes;
|
import net.osmand.osm.MapPoiTypes;
|
||||||
import net.osmand.osm.PoiType;
|
import net.osmand.osm.PoiType;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.OsmandSettings;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
||||||
|
@ -464,9 +466,15 @@ public class AmenityMenuBuilder extends MenuBuilder {
|
||||||
buildAmenityRow(view, wikiInfo);
|
buildAmenityRow(view, wikiInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OsmandSettings st = ((OsmandApplication) mapActivity.getApplicationContext()).getSettings();
|
||||||
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationName(app,
|
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationName(app,
|
||||||
amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(), true)
|
amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(), true)
|
||||||
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
||||||
|
if (st.COORDINATES_FORMAT.get() != PointDescription.OLC_FORMAT)
|
||||||
|
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationOlcName(
|
||||||
|
amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude())
|
||||||
|
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildAmenityRow(View view, AmenityInfoRow info) {
|
public void buildAmenityRow(View view, AmenityInfoRow info) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import android.view.View;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.osm.MapPoiTypes;
|
import net.osmand.osm.MapPoiTypes;
|
||||||
import net.osmand.osm.PoiType;
|
import net.osmand.osm.PoiType;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.OsmandSettings;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
import net.osmand.plus.mapcontextmenu.MenuBuilder;
|
||||||
|
@ -71,8 +73,13 @@ public class EditPOIMenuBuilder extends MenuBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OsmandSettings st = ((OsmandApplication) mapActivity.getApplicationContext()).getSettings();
|
||||||
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationName(app,
|
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationName(app,
|
||||||
osmPoint.getLatitude(), osmPoint.getLongitude(), true)
|
osmPoint.getLatitude(), osmPoint.getLongitude(), true)
|
||||||
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
||||||
|
if (st.COORDINATES_FORMAT.get() != PointDescription.OLC_FORMAT)
|
||||||
|
buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationOlcName(
|
||||||
|
osmPoint.getLatitude(), osmPoint.getLongitude())
|
||||||
|
.replaceAll("\n", " "), 0, false, null, false, 0, false, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
|
|
||||||
|
import com.google.openlocationcode.OpenLocationCode;
|
||||||
import com.jwetherell.openmap.common.LatLonPoint;
|
import com.jwetherell.openmap.common.LatLonPoint;
|
||||||
import com.jwetherell.openmap.common.UTMPoint;
|
import com.jwetherell.openmap.common.UTMPoint;
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import net.osmand.LocationConvert;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.plus.IconsCache;
|
import net.osmand.plus.IconsCache;
|
||||||
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
|
||||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
@ -49,6 +51,8 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
private static final String QUICK_SEARCH_COORDS_NORTH_KEY = "quick_search_coords_north_key";
|
private static final String QUICK_SEARCH_COORDS_NORTH_KEY = "quick_search_coords_north_key";
|
||||||
private static final String QUICK_SEARCH_COORDS_EAST_KEY = "quick_search_coords_east_key";
|
private static final String QUICK_SEARCH_COORDS_EAST_KEY = "quick_search_coords_east_key";
|
||||||
private static final String QUICK_SEARCH_COORDS_ZONE_KEY = "quick_search_coords_zone_key";
|
private static final String QUICK_SEARCH_COORDS_ZONE_KEY = "quick_search_coords_zone_key";
|
||||||
|
private static final String QUICK_SEARCH_COORDS_OLC_KEY = "quick_search_coords_olc_key";
|
||||||
|
private static final String QUICK_SEARCH_COORDS_OLC_INFO_KEY = "quick_search_coords_olc_info_key";
|
||||||
private static final String QUICK_SEARCH_COORDS_FORMAT_KEY = "quick_search_coords_format_key";
|
private static final String QUICK_SEARCH_COORDS_FORMAT_KEY = "quick_search_coords_format_key";
|
||||||
private static final String QUICK_SEARCH_COORDS_USE_MAP_CENTER_KEY = "quick_search_coords_use_map_center_key";
|
private static final String QUICK_SEARCH_COORDS_USE_MAP_CENTER_KEY = "quick_search_coords_use_map_center_key";
|
||||||
private static final String QUICK_SEARCH_COORDS_TEXT_KEY = "quick_search_coords_text_key";
|
private static final String QUICK_SEARCH_COORDS_TEXT_KEY = "quick_search_coords_text_key";
|
||||||
|
@ -61,6 +65,8 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
private EditText northingEdit;
|
private EditText northingEdit;
|
||||||
private EditText eastingEdit;
|
private EditText eastingEdit;
|
||||||
private EditText zoneEdit;
|
private EditText zoneEdit;
|
||||||
|
private EditText olcEdit;
|
||||||
|
private TextView olcInfo;
|
||||||
private EditText formatEdit;
|
private EditText formatEdit;
|
||||||
private int currentFormat = PointDescription.FORMAT_DEGREES;
|
private int currentFormat = PointDescription.FORMAT_DEGREES;
|
||||||
|
|
||||||
|
@ -113,11 +119,14 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
|
|
||||||
String defaultLat = "";
|
String defaultLat = "";
|
||||||
String defaultZone = "";
|
String defaultZone = "";
|
||||||
|
String defaultOlc = "";
|
||||||
if (getArguments() != null) {
|
if (getArguments() != null) {
|
||||||
String text = getArguments().getString(QUICK_SEARCH_COORDS_TEXT_KEY);
|
String text = getArguments().getString(QUICK_SEARCH_COORDS_TEXT_KEY);
|
||||||
if (!Algorithms.isEmpty(text)) {
|
if (!Algorithms.isEmpty(text)) {
|
||||||
if (currentFormat == PointDescription.UTM_FORMAT) {
|
if (currentFormat == PointDescription.UTM_FORMAT) {
|
||||||
defaultZone = text.trim();
|
defaultZone = text.trim();
|
||||||
|
} else if (currentFormat == PointDescription.OLC_FORMAT) {
|
||||||
|
defaultOlc = text.trim();
|
||||||
} else {
|
} else {
|
||||||
defaultLat = text.trim();
|
defaultLat = text.trim();
|
||||||
}
|
}
|
||||||
|
@ -129,6 +138,8 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
String northingStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_NORTH_KEY, "");
|
String northingStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_NORTH_KEY, "");
|
||||||
String eastingStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_EAST_KEY, "");
|
String eastingStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_EAST_KEY, "");
|
||||||
String zoneStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_ZONE_KEY, defaultZone);
|
String zoneStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_ZONE_KEY, defaultZone);
|
||||||
|
String olcStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_OLC_KEY, defaultOlc);
|
||||||
|
String olcInfoStr = getStringValue(savedInstanceState, QUICK_SEARCH_COORDS_OLC_INFO_KEY, defaultOlc);
|
||||||
|
|
||||||
if (savedInstanceState != null)
|
if (savedInstanceState != null)
|
||||||
currentFormat = savedInstanceState.getInt(QUICK_SEARCH_COORDS_FORMAT_KEY, -1);
|
currentFormat = savedInstanceState.getInt(QUICK_SEARCH_COORDS_FORMAT_KEY, -1);
|
||||||
|
@ -147,6 +158,8 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
northingEdit = ((EditText) view.findViewById(R.id.northingEditText));
|
northingEdit = ((EditText) view.findViewById(R.id.northingEditText));
|
||||||
eastingEdit = ((EditText) view.findViewById(R.id.eastingEditText));
|
eastingEdit = ((EditText) view.findViewById(R.id.eastingEditText));
|
||||||
zoneEdit = ((EditText) view.findViewById(R.id.zoneEditText));
|
zoneEdit = ((EditText) view.findViewById(R.id.zoneEditText));
|
||||||
|
olcEdit = ((EditText) view.findViewById(R.id.olcEditText));
|
||||||
|
olcInfo = ((TextView) view.findViewById(R.id.olcInfoTextView));
|
||||||
formatEdit = ((EditText) view.findViewById(R.id.formatEditText));
|
formatEdit = ((EditText) view.findViewById(R.id.formatEditText));
|
||||||
|
|
||||||
latEdit.setText(latStr);
|
latEdit.setText(latStr);
|
||||||
|
@ -159,6 +172,9 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
eastingEdit.setSelection(eastingStr.length());
|
eastingEdit.setSelection(eastingStr.length());
|
||||||
zoneEdit.setText(zoneStr);
|
zoneEdit.setText(zoneStr);
|
||||||
zoneEdit.setSelection(zoneStr.length());
|
zoneEdit.setSelection(zoneStr.length());
|
||||||
|
olcEdit.setText(olcStr);
|
||||||
|
olcEdit.setSelection(olcStr.length());
|
||||||
|
olcInfo.setText(olcInfoStr);
|
||||||
|
|
||||||
formatEdit.setText(PointDescription.formatToHumanString(app, currentFormat));
|
formatEdit.setText(PointDescription.formatToHumanString(app, currentFormat));
|
||||||
formatEdit.setOnClickListener(new View.OnClickListener() {
|
formatEdit.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@ -188,6 +204,7 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
northingEdit.addTextChangedListener(textWatcher);
|
northingEdit.addTextChangedListener(textWatcher);
|
||||||
eastingEdit.addTextChangedListener(textWatcher);
|
eastingEdit.addTextChangedListener(textWatcher);
|
||||||
zoneEdit.addTextChangedListener(textWatcher);
|
zoneEdit.addTextChangedListener(textWatcher);
|
||||||
|
olcEdit.addTextChangedListener(textWatcher);
|
||||||
|
|
||||||
OnEditorActionListener doneListener = new OnEditorActionListener() {
|
OnEditorActionListener doneListener = new OnEditorActionListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -203,6 +220,7 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
|
|
||||||
lonEdit.setOnEditorActionListener(doneListener);
|
lonEdit.setOnEditorActionListener(doneListener);
|
||||||
zoneEdit.setOnEditorActionListener(doneListener);
|
zoneEdit.setOnEditorActionListener(doneListener);
|
||||||
|
olcEdit.setOnEditorActionListener(doneListener);
|
||||||
|
|
||||||
IconsCache ic = app.getIconsCache();
|
IconsCache ic = app.getIconsCache();
|
||||||
((ImageView) view.findViewById(R.id.latitudeImage))
|
((ImageView) view.findViewById(R.id.latitudeImage))
|
||||||
|
@ -251,7 +269,15 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
zoneClearButton.setOnClickListener(new View.OnClickListener() {
|
zoneClearButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
zoneEdit.setText("");
|
olcEdit.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ImageButton olcClearButton = (ImageButton) view.findViewById(R.id.olcClearButton);
|
||||||
|
olcClearButton.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_remove_dark));
|
||||||
|
olcClearButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
olcEdit.setText("");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ImageButton formatSelectButton = (ImageButton) view.findViewById(R.id.formatSelectButton);
|
ImageButton formatSelectButton = (ImageButton) view.findViewById(R.id.formatSelectButton);
|
||||||
|
@ -300,11 +326,15 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
final TextView northEdit = ((TextView) view.findViewById(R.id.northingEditText));
|
final TextView northEdit = ((TextView) view.findViewById(R.id.northingEditText));
|
||||||
final TextView eastEdit = ((TextView) view.findViewById(R.id.eastingEditText));
|
final TextView eastEdit = ((TextView) view.findViewById(R.id.eastingEditText));
|
||||||
final TextView zoneEdit = ((TextView) view.findViewById(R.id.zoneEditText));
|
final TextView zoneEdit = ((TextView) view.findViewById(R.id.zoneEditText));
|
||||||
|
final TextView olcEdit = ((TextView) view.findViewById(R.id.olcEditText));
|
||||||
|
final TextView olcInfo = ((TextView) view.findViewById(R.id.olcInfoTextView));
|
||||||
outState.putString(QUICK_SEARCH_COORDS_LAT_KEY, latEdit.getText().toString());
|
outState.putString(QUICK_SEARCH_COORDS_LAT_KEY, latEdit.getText().toString());
|
||||||
outState.putString(QUICK_SEARCH_COORDS_LON_KEY, lonEdit.getText().toString());
|
outState.putString(QUICK_SEARCH_COORDS_LON_KEY, lonEdit.getText().toString());
|
||||||
outState.putString(QUICK_SEARCH_COORDS_NORTH_KEY, northEdit.getText().toString());
|
outState.putString(QUICK_SEARCH_COORDS_NORTH_KEY, northEdit.getText().toString());
|
||||||
outState.putString(QUICK_SEARCH_COORDS_EAST_KEY, eastEdit.getText().toString());
|
outState.putString(QUICK_SEARCH_COORDS_EAST_KEY, eastEdit.getText().toString());
|
||||||
outState.putString(QUICK_SEARCH_COORDS_ZONE_KEY, zoneEdit.getText().toString());
|
outState.putString(QUICK_SEARCH_COORDS_ZONE_KEY, zoneEdit.getText().toString());
|
||||||
|
outState.putString(QUICK_SEARCH_COORDS_OLC_KEY, olcEdit.getText().toString());
|
||||||
|
outState.putString(QUICK_SEARCH_COORDS_OLC_INFO_KEY, olcInfo.getText().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,12 +435,44 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateControlsVisibility() {
|
private void updateControlsVisibility() {
|
||||||
boolean utm = currentFormat == PointDescription.UTM_FORMAT;
|
if (currentFormat == PointDescription.OLC_FORMAT) {
|
||||||
view.findViewById(R.id.eastingLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.eastingLayout).setVisibility(View.GONE);
|
||||||
view.findViewById(R.id.northingLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.northingLayout).setVisibility(View.GONE);
|
||||||
view.findViewById(R.id.zoneLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.zoneLayout).setVisibility(View.GONE);
|
||||||
view.findViewById(R.id.latitudeLayout).setVisibility(!utm ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.olcLayout).setVisibility(View.VISIBLE);
|
||||||
view.findViewById(R.id.longitudeLayout).setVisibility(!utm ? View.VISIBLE : View.GONE);
|
view.findViewById(R.id.olcInfoLayout).setVisibility(View.VISIBLE);
|
||||||
|
view.findViewById(R.id.latitudeLayout).setVisibility(View.GONE);
|
||||||
|
view.findViewById(R.id.longitudeLayout).setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
boolean utm = currentFormat == PointDescription.UTM_FORMAT;
|
||||||
|
view.findViewById(R.id.eastingLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
||||||
|
view.findViewById(R.id.northingLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
||||||
|
view.findViewById(R.id.zoneLayout).setVisibility(utm ? View.VISIBLE : View.GONE);
|
||||||
|
view.findViewById(R.id.olcLayout).setVisibility(View.GONE);
|
||||||
|
view.findViewById(R.id.olcInfoLayout).setVisibility(View.GONE);
|
||||||
|
view.findViewById(R.id.latitudeLayout).setVisibility(!utm ? View.VISIBLE : View.GONE);
|
||||||
|
view.findViewById(R.id.longitudeLayout).setVisibility(!utm ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String provideOlcInfo(String olcString) {
|
||||||
|
try {
|
||||||
|
if (!OpenLocationCode.isValidCode(olcString))
|
||||||
|
return getContext().getString(R.string.navigate_point_olc_info_invalid);
|
||||||
|
OpenLocationCode olc = new OpenLocationCode(olcString);
|
||||||
|
if (olc.isShort())
|
||||||
|
return getContext().getString(R.string.navigate_point_olc_info_short);
|
||||||
|
OpenLocationCode.CodeArea area = olc.decode();
|
||||||
|
int areaWidth = (int)Math.ceil(MapUtils.getDistance(area.getNorthLatitude(), area.getWestLongitude(),
|
||||||
|
area.getNorthLatitude(), area.getEastLongitude()));
|
||||||
|
int areaHeight = (int)Math.ceil(MapUtils.getDistance(area.getNorthLatitude(), area.getWestLongitude(),
|
||||||
|
area.getSouthLatitude(), area.getWestLongitude()));
|
||||||
|
return getContext().getString(R.string.navigate_point_olc_info_area,
|
||||||
|
OsmAndFormatter.getFormattedDistance(areaWidth, getMyApplication()),
|
||||||
|
OsmAndFormatter.getFormattedDistance(areaHeight, getMyApplication()));
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
return getContext().getString(R.string.navigate_point_olc_info_invalid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean applyFormat(int format) {
|
private boolean applyFormat(int format) {
|
||||||
|
@ -430,11 +492,27 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
zoneEdit.setText(pnt.zone_number + "" + pnt.zone_letter);
|
zoneEdit.setText(pnt.zone_number + "" + pnt.zone_letter);
|
||||||
northingEdit.setText(((long) pnt.northing) + "");
|
northingEdit.setText(((long) pnt.northing) + "");
|
||||||
eastingEdit.setText(((long) pnt.easting) + "");
|
eastingEdit.setText(((long) pnt.easting) + "");
|
||||||
|
} else if (prevFormat == PointDescription.OLC_FORMAT) {
|
||||||
|
zoneEdit.setText(olcEdit.getText());
|
||||||
|
northingEdit.setText("");
|
||||||
|
eastingEdit.setText("");
|
||||||
} else {
|
} else {
|
||||||
zoneEdit.setText(latEdit.getText());
|
zoneEdit.setText(latEdit.getText());
|
||||||
northingEdit.setText("");
|
northingEdit.setText("");
|
||||||
eastingEdit.setText("");
|
eastingEdit.setText("");
|
||||||
}
|
}
|
||||||
|
} else if (currentFormat == PointDescription.OLC_FORMAT) {
|
||||||
|
if (currentLatLon != null) {
|
||||||
|
String olc = OpenLocationCode.encode(currentLatLon.getLatitude(), currentLatLon.getLongitude());
|
||||||
|
olcEdit.setText(olc);
|
||||||
|
olcInfo.setText(provideOlcInfo(olc));
|
||||||
|
} else if (prevFormat == PointDescription.UTM_FORMAT) {
|
||||||
|
olcEdit.setText(zoneEdit.getText());
|
||||||
|
olcInfo.setText(provideOlcInfo(olcEdit.getText().toString()));
|
||||||
|
} else {
|
||||||
|
olcEdit.setText(latEdit.getText());
|
||||||
|
olcInfo.setText(provideOlcInfo(olcEdit.getText().toString()));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentLatLon != null) {
|
if (currentLatLon != null) {
|
||||||
latEdit.setText(LocationConvert.convert(MapUtils.checkLatitude(currentLatLon.getLatitude()), currentFormat));
|
latEdit.setText(LocationConvert.convert(MapUtils.checkLatitude(currentLatLon.getLatitude()), currentFormat));
|
||||||
|
@ -442,6 +520,9 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
} else if (prevFormat == PointDescription.UTM_FORMAT) {
|
} else if (prevFormat == PointDescription.UTM_FORMAT) {
|
||||||
latEdit.setText(zoneEdit.getText());
|
latEdit.setText(zoneEdit.getText());
|
||||||
lonEdit.setText("");
|
lonEdit.setText("");
|
||||||
|
} else if (prevFormat == PointDescription.OLC_FORMAT) {
|
||||||
|
latEdit.setText(olcEdit.getText());
|
||||||
|
lonEdit.setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return currentLatLon != null;
|
return currentLatLon != null;
|
||||||
|
@ -462,6 +543,12 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
UTMPoint upoint = new UTMPoint(northing, easting, z, c);
|
UTMPoint upoint = new UTMPoint(northing, easting, z, c);
|
||||||
LatLonPoint ll = upoint.toLatLonPoint();
|
LatLonPoint ll = upoint.toLatLonPoint();
|
||||||
loc = new LatLon(ll.getLatitude(), ll.getLongitude());
|
loc = new LatLon(ll.getLatitude(), ll.getLongitude());
|
||||||
|
} else if (currentFormat == LocationConvert.OLC_FORMAT) {
|
||||||
|
String olcText = olcEdit.getText().toString();
|
||||||
|
olcInfo.setText(provideOlcInfo(olcText));
|
||||||
|
// can throw exception for invalid OLC string
|
||||||
|
OpenLocationCode.CodeArea codeArea = OpenLocationCode.decode(olcText);
|
||||||
|
loc = new LatLon(codeArea.getCenterLatitude(), codeArea.getCenterLongitude());
|
||||||
} else {
|
} else {
|
||||||
double lat = LocationConvert.convert(latEdit.getText().toString(), true);
|
double lat = LocationConvert.convert(latEdit.getText().toString(), true);
|
||||||
double lon = LocationConvert.convert(lonEdit.getText().toString(), true);
|
double lon = LocationConvert.convert(lonEdit.getText().toString(), true);
|
||||||
|
@ -543,11 +630,12 @@ public class QuickSearchCoordinatesFragment extends DialogFragment implements Os
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final QuickSearchCoordinatesFragment parent = (QuickSearchCoordinatesFragment) getParentFragment();
|
final QuickSearchCoordinatesFragment parent = (QuickSearchCoordinatesFragment) getParentFragment();
|
||||||
String[] entries = new String[4];
|
String[] entries = new String[5];
|
||||||
entries[0] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_DEGREES);
|
entries[0] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_DEGREES);
|
||||||
entries[1] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_MINUTES);
|
entries[1] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_MINUTES);
|
||||||
entries[2] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_SECONDS);
|
entries[2] = PointDescription.formatToHumanString(getContext(), PointDescription.FORMAT_SECONDS);
|
||||||
entries[3] = PointDescription.formatToHumanString(getContext(), PointDescription.UTM_FORMAT);
|
entries[3] = PointDescription.formatToHumanString(getContext(), PointDescription.UTM_FORMAT);
|
||||||
|
entries[4] = PointDescription.formatToHumanString(getContext(), PointDescription.OLC_FORMAT);
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
builder.setTitle(R.string.coords_format)
|
builder.setTitle(R.string.coords_format)
|
||||||
|
|
Loading…
Reference in a new issue