
de.alpharogroup.jgeohash.GeoHashExtensions Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010 Asterios Raptis
*
* Licensed 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 de.alpharogroup.jgeohash;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import de.alpharogroup.jgeohash.model.FirstAndSecondRingRegion;
import de.alpharogroup.jgeohash.model.FirstRingRegion;
/**
* The class {@link GeoHashExtensions}.
* This class is based on http://en.wikipedia.org/wiki/Geohash.
*/
public class GeoHashExtensions
{
/**
* The Constant char map BASE_32.
* */
private final static char[] BASE_32 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'b',
'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z' };
/** The Constant DECODE_MAP. */
private final static Map DECODE_MAP = new HashMap<>();
static
{
int counter = 0;
for (final char c : BASE_32)
{
DECODE_MAP.put(c, counter++);
}
}
/** The precision. */
private static final int precision = 12;
/** The bits. */
private static final int[] bits = { 16, 8, 4, 2, 1 };
/**
* Decode the given geohash into a latitude and longitude.
*
* @param geohash
* the geohash
* @return the double[]
*/
public static double[] decode(final String geohash)
{
if ((geohash == null) || geohash.isEmpty())
{
throw new IllegalArgumentException("Argument geohash should not be null.");
}
boolean even = true;
double latitudeError = 90.0;
double longitudeError = 180.0;
double latitude;
double longitude;
final double[] latitudeInterval = { -90.0, 90.0 };
final double[] longitudeInterval = { -180.0, 180.0 };
for (int i = 0; i < geohash.length(); i++)
{
final int cd = DECODE_MAP.get(geohash.charAt(i));
for (int j = 0; j < bits.length; j++)
{
final int mask = bits[j];
if (even)
{
longitudeError /= 2;
if ((cd & mask) != 0)
{
longitudeInterval[0] = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
}
else
{
longitudeInterval[1] = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
}
}
else
{
latitudeError /= 2;
if ((cd & mask) != 0)
{
latitudeInterval[0] = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
}
else
{
latitudeInterval[1] = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
}
}
even = !even;
}
}
latitude = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
longitude = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
return new double[] { latitude, longitude, latitudeError, longitudeError };
}
/**
* Decodes the given geohash into a latitude and longitude.
*
* @param geohash
* the geohash
* @return the double[]
*/
public static double[] decodeAndRound(final String geohash)
{
final double[] ge = decode(geohash);
double latitude = ge[0];
double longitude = ge[1];
final double latitudeError = ge[2];
final double longitudeError = ge[3];
final double latitudePrecision = Math.max(1, Math.round(-Math.log10(latitudeError))) - 1;
final double longitudePrecision = Math.max(1, Math.round(-Math.log10(longitudeError))) - 1;
latitude = getPrecision(latitude, latitudePrecision);
longitude = getPrecision(longitude, longitudePrecision);
return new double[] { latitude, longitude };
}
/**
* Encodes the given latitude and longitude into a geohash code.
*
* @param latitude
* the latitude
* @param longitude
* the longitude
* @return The generated geohash from the given latitude and longitude.
*/
public static String encode(final double latitude, final double longitude)
{
final StringBuilder geohash = new StringBuilder();
boolean even = true;
int bit = 0;
int ch = 0;
final double[] latitudeInterval = { -90.0, 90.0 };
final double[] longitudeInterval = { -180.0, 180.0 };
while (geohash.length() < precision)
{
double mid = 0.0;
if (even)
{
mid = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
if (longitude > mid)
{
ch |= bits[bit];
longitudeInterval[0] = mid;
}
else
{
longitudeInterval[1] = mid;
}
}
else
{
mid = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
if (latitude > mid)
{
ch |= bits[bit];
latitudeInterval[0] = mid;
}
else
{
latitudeInterval[1] = mid;
}
}
even = !even;
if (bit < 4)
{
bit++;
}
else
{
geohash.append(BASE_32[ch]);
bit = 0;
ch = 0;
}
}
return geohash.toString();
}
/**
* Gets the adjacent from the given direction. For instance if direction is 'top' then the top
* adjacent geohash code will be returned.
*
* @param geohash
* the geohash
* @param direction
* the direction
* @return the geohash code for the adjacent from the given direction.
*/
public static String getAdjacent(final String geohash, final String direction)
{
if ((geohash == null) || geohash.isEmpty())
{
throw new IllegalArgumentException("Argument geohash should not be null or empty.");
}
if ((direction == null) || direction.isEmpty())
{
throw new IllegalArgumentException("Argument direction should not be null or empty.");
}
final String lowerCaseGeohash = geohash.toLowerCase();
final char lastChar = lowerCaseGeohash.charAt(lowerCaseGeohash.length() - 1);
final int modulo = lowerCaseGeohash.length() % 2;
final String type = modulo == 0 ? Adjacent.ODD : Adjacent.EVEN;
String base = lowerCaseGeohash.substring(0, lowerCaseGeohash.length() - 1);
final Map borderDirection = Adjacent.Borders.borders.get(direction);
final String borderDirectionType = borderDirection.get(type);
final int indexOfLastChar = borderDirectionType.indexOf(lastChar);
if ((indexOfLastChar != -1) && !base.isEmpty())
{
base = getAdjacent(base, direction);
}
final Map neighborsDirection = Adjacent.Neighbors.neighbors.get(direction);
final String neighborsDirectionType = neighborsDirection.get(type);
final int i = neighborsDirectionType.indexOf(lastChar);
final char r = BASE_32[i];
return base + r;
}
/**
* Gets the adjacent from the given directions. For instance if directions is 'top' and 'feft'
* then the topleft adjacent geohash code will be returned.
*
* @param geohash
* the geohash
* @param directions
* the directions
* @return the geohash code for the adjacent from the given directions.
*/
public static String getAdjacent(final String geohash, final String... directions)
{
String geohashresult = geohash;
for (final String direction : directions)
{
geohashresult = getAdjacent(geohashresult, direction);
}
return geohashresult;
}
/**
* Gets the all adjacent areas list.
*
* @param geohash
* the geohash
* @return the all adjacent areas list
*/
public static List getAllAdjacentAreasList(final String geohash)
{
if ((geohash == null) || geohash.isEmpty())
{
throw new IllegalArgumentException("Argument geohash should not be null.");
}
final List adjacentAreas = new ArrayList<>();
final String top = GeoHashExtensions.getAdjacent(geohash, Adjacent.TOP);
final String bottom = GeoHashExtensions.getAdjacent(geohash, Adjacent.BOTTOM);
final String right = GeoHashExtensions.getAdjacent(geohash, Adjacent.RIGHT);
final String left = GeoHashExtensions.getAdjacent(geohash, Adjacent.LEFT);
final String topleft = GeoHashExtensions.getAdjacent(left, Adjacent.TOP);
final String topright = GeoHashExtensions.getAdjacent(right, Adjacent.TOP);
final String bottomright = GeoHashExtensions.getAdjacent(right, Adjacent.BOTTOM);
final String bottomleft = GeoHashExtensions.getAdjacent(left, Adjacent.BOTTOM);
adjacentAreas.add(geohash);
adjacentAreas.add(top);
adjacentAreas.add(topright);
adjacentAreas.add(right);
adjacentAreas.add(bottomright);
adjacentAreas.add(bottom);
adjacentAreas.add(bottomleft);
adjacentAreas.add(left);
adjacentAreas.add(topleft);
return adjacentAreas;
}
/**
* Gets the geohash cells around the given geohash cell. With other words it gets eight cells
* around the given geohash cell so the first ring inclusive the given geohash cell.
*
* @param geohash
* the geohash
* @return all geohash cells around the given geohash cell.
*/
public static Map getAllAdjacentAreasMap(final String geohash)
{
if ((geohash == null) || geohash.isEmpty())
{
throw new IllegalArgumentException("Argument geohash should not be null.");
}
final String top = GeoHashExtensions.getAdjacent(geohash, Adjacent.TOP);
final String bottom = GeoHashExtensions.getAdjacent(geohash, Adjacent.BOTTOM);
final String right = GeoHashExtensions.getAdjacent(geohash, Adjacent.RIGHT);
final String left = GeoHashExtensions.getAdjacent(geohash, Adjacent.LEFT);
final String topleft = GeoHashExtensions.getAdjacent(left, Adjacent.TOP);
final String topright = GeoHashExtensions.getAdjacent(right, Adjacent.TOP);
final String bottomright = GeoHashExtensions.getAdjacent(right, Adjacent.BOTTOM);
final String bottomleft = GeoHashExtensions.getAdjacent(left, Adjacent.BOTTOM);
final Map adjacentAreas = new LinkedHashMap<>();
adjacentAreas.put(Adjacent.CENTER, geohash);
adjacentAreas.put(Adjacent.TOP, top);
adjacentAreas.put(Adjacent.BOTTOM, bottom);
adjacentAreas.put(Adjacent.RIGHT, right);
adjacentAreas.put(Adjacent.LEFT, left);
adjacentAreas.put(Adjacent.TOP_LEFT, topleft);
adjacentAreas.put(Adjacent.TOP_RIGHT, topright);
adjacentAreas.put(Adjacent.BOTTOM_RIGHT, bottomright);
adjacentAreas.put(Adjacent.BOTTOM_LEFT, bottomleft);
return adjacentAreas;
}
/**
* Gets the geohash cells of the first and second ring region around the given geohash cell as a
* {@link FirstAndSecondRingRegion} object.
*
* @param geohash
* the geohash cell.
* @return the {@link FirstAndSecondRingRegion} that encapsulates the cells of the first and
* second ring region around the given geohash cell.
*/
public static FirstAndSecondRingRegion getFirstAndSecondRingRegion(final String geohash)
{
return new FirstAndSecondRingRegion(geohash);
}
/**
* Gets the geohash cells around the given geohash cell as a {@link FirstRingRegion} object.
*
* @param geohash
* the geohash cell.
* @return the {@link FirstRingRegion} object calculated from the given geohash value.
*/
public static FirstRingRegion getFirstRingRegion(final String geohash)
{
return new FirstRingRegion(geohash);
}
/**
* Gets the latitude from the given geohash value.
*
* @param geohash
* the geohash
* @return the latitude
*/
public static double getLatitude(final String geohash)
{
return decodeAndRound(geohash)[0];
}
/**
* Gets the longitude from the given geohash value.
*
* @param geohash
* the geohash
* @return the longitude
*/
public static double getLongitude(final String geohash)
{
return decodeAndRound(geohash)[1];
}
/**
* Gets the precision.
*
* @param x
* the x
* @param precision
* the precision
* @return the precision
*/
private static double getPrecision(final double x, final double precision)
{
final double base = Math.pow(10, -precision);
final double diff = x % base;
return x - diff;
}
/**
* Gets the eight cells around the given geohash cell so the first ring inclusive the given
* geohash cell and cells from the second ring. The result is 24 cells plus the given geohash
* cell.
*
* @param geohash
* the geohash
* @return the eight cells around the given geohash cell so the first ring inclusive the given
* geohash cell and cells from the second ring.
*/
public static Map getTwentyFiveAreasMap(final String geohash)
{
final Map adjacentAreas = getAllAdjacentAreasMap(geohash);
final String topTop = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.TOP),
Adjacent.TOP);
final String topLeftTop = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.TOP_LEFT),
Adjacent.TOP);
final String topLeftTopLeft = GeoHashExtensions.getAdjacent(topLeftTop, Adjacent.LEFT);
final String topLeftLeft = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.TOP_LEFT),
Adjacent.LEFT);
final String topRightTop = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.TOP_RIGHT),
Adjacent.TOP);
final String topRightTopRight = GeoHashExtensions.getAdjacent(topRightTop, Adjacent.RIGHT);
final String topRightRight = GeoHashExtensions.getAdjacent(
adjacentAreas.get(Adjacent.TOP_RIGHT), Adjacent.RIGHT);
final String rightRight = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.RIGHT),
Adjacent.RIGHT);
final String bottomRightRight = GeoHashExtensions.getAdjacent(
adjacentAreas.get(Adjacent.BOTTOM_RIGHT), Adjacent.RIGHT);
final String bottomRightBottom = GeoHashExtensions.getAdjacent(
adjacentAreas.get(Adjacent.BOTTOM_RIGHT), Adjacent.BOTTOM);
final String bottomRightBottomRight = GeoHashExtensions.getAdjacent(bottomRightBottom,
Adjacent.RIGHT);
final String bottomBottom = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.BOTTOM),
Adjacent.BOTTOM);
final String bottomLeftBottom = GeoHashExtensions.getAdjacent(
adjacentAreas.get(Adjacent.BOTTOM_LEFT), Adjacent.BOTTOM);
final String bottomLeftBottomLeft = GeoHashExtensions.getAdjacent(bottomLeftBottom,
Adjacent.LEFT);
final String bottomLeftLeft = GeoHashExtensions.getAdjacent(
adjacentAreas.get(Adjacent.BOTTOM_LEFT), Adjacent.LEFT);
final String leftLeft = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.LEFT),
Adjacent.LEFT);
adjacentAreas.put(Adjacent.TOP_LEFT_TOP, topLeftTop);
adjacentAreas.put(Adjacent.TOP_LEFT_TOP_LEFT, topLeftTopLeft);
adjacentAreas.put(Adjacent.TOP_LEFT_LEFT, topLeftLeft);
adjacentAreas.put(Adjacent.TOP_TOP, topTop);
adjacentAreas.put(Adjacent.TOP_RIGHT_TOP, topRightTop);
adjacentAreas.put(Adjacent.TOP_RIGHT_RIGHT, topRightRight);
adjacentAreas.put(Adjacent.TOP_RIGHT_TOP_RIGHT, topRightTopRight);
adjacentAreas.put(Adjacent.RIGHT_RIGHT, rightRight);
adjacentAreas.put(Adjacent.BOTTOM_RIGHT_RIGHT, bottomRightRight);
adjacentAreas.put(Adjacent.BOTTOM_RIGHT_BOTTOM, bottomRightBottom);
adjacentAreas.put(Adjacent.BOTTOM_RIGHT_BOTTOM_RIGHT, bottomRightBottomRight);
adjacentAreas.put(Adjacent.BOTTOM_BOTTOM, bottomBottom);
adjacentAreas.put(Adjacent.BOTTOM_LEFT_BOTTOM, bottomLeftBottom);
adjacentAreas.put(Adjacent.BOTTOM_LEFT_BOTTOM_LEFT, bottomLeftBottomLeft);
adjacentAreas.put(Adjacent.BOTTOM_LEFT_LEFT, bottomLeftLeft);
adjacentAreas.put(Adjacent.LEFT_LEFT, leftLeft);
return adjacentAreas;
}
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(final String[] args)
{
final String alterTeichwegGeohash = "u1x0v54rmjwej";
final String gc1 = GeoHashExtensions.encode(30.0, -90.0);
final String gc2 = GeoHashExtensions.encode(51.4797, -0.0124);
final String geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
System.out.println("geohash:" + geohash);
System.out.println("gc1:" + gc1);
System.out.println("gc2:" + gc2);
double[] gd1 = GeoHashExtensions.decodeAndRound(gc1);
double[] gd2 = GeoHashExtensions.decodeAndRound(gc2);
System.out.println(gd1[0] + ", " + gd1[1]);
System.out.println(gd2[0] + ", " + gd2[1]);
gd1 = GeoHashExtensions.decode(gc1);
gd2 = GeoHashExtensions.decode(gc2);
final double[] decoded = GeoHashExtensions.decode(geohash);
System.out.println(gd1[0] + ", " + gd1[1]);
System.out.println(gd2[0] + ", " + gd2[1]);
System.out.println(decoded[0] + ", " + decoded[1]);
final String geohashTest = alterTeichwegGeohash;
final String top = GeoHashExtensions.getAdjacent(geohashTest, "top");
System.out.println("top:\t\t" + top);
final String bottom = GeoHashExtensions.getAdjacent(geohashTest, "bottom");
System.out.println("bottom:\t\t" + bottom);
final String right = GeoHashExtensions.getAdjacent(geohashTest, "right");
System.out.println("right:\t\t" + right);
final String left = GeoHashExtensions.getAdjacent(geohashTest, "left");
System.out.println("left:\t\t" + left);
final String topleft = GeoHashExtensions.getAdjacent(left, "top");
System.out.println("topleft:\t" + topleft);
final String topright = GeoHashExtensions.getAdjacent(right, "top");
System.out.println("topright:\t" + topright);
final String bottomright = GeoHashExtensions.getAdjacent(right, "bottom");
System.out.println("bottomright:\t" + bottomright);
final String bottomleft = GeoHashExtensions.getAdjacent(left, "bottom");
System.out.println("bottomleft:\t" + bottomleft);
final String subGeohash = geohash.substring(0, 7);
final Map adjacentAreas = GeoHashExtensions.getAllAdjacentAreasMap(subGeohash);
System.out.println(adjacentAreas);
System.out.println("=======================================");
final List aa = GeoHashExtensions.getAllAdjacentAreasList(subGeohash);
System.out.println(aa);
System.out.println("=======================================");
final GeoHashPoint geohashPoint1 = new GeoHashPoint(geohash);
final GeoHashPoint geohashPoint2 = new GeoHashPoint(geohash);
System.out.println(geohashPoint1);
System.out.println(geohashPoint2);
final int c = geohashPoint1.compareTo(geohashPoint2);
System.out.println(c);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy