package com.walker.location; import com.walker.infrastructure.utils.StringUtils; import java.util.ArrayList; import java.util.List; /** * 计算GeoHash工具类,该对象可创建单例。 *
 *     1 = 2500km;
 *     2 = 630km;
 *     3 = 78km;
 *     4 = 30km;
 *     5 = 2.4km;
 *     6 = 610m;
 *     7 = 76m;
 *     8 = 19m;
 * 
* @author 时克英 * @date 2023-04-18 */ public class GeoHashHelper { public final double Max_Lat = 90; public final double Min_Lat = -90; public final double Max_Lng = 180; public final double Min_Lng = -180; private final int length = 20; private final double latUnit = (Max_Lat - Min_Lat) / (1 << 20); private final double lngUnit = (Max_Lng - Min_Lng) / (1 << 20); private final String[] base32Lookup = {"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"}; private void convert(double min, double max, double value, List list) { if (list.size() > (length - 1)) { return; } double mid = (max + min) / 2; if (value < mid) { // list.add('0'); list.add(StringUtils.CHAR_ZERO); convert(min, mid, value, list); } else { // list.add('1'); list.add(StringUtils.CHAR_ONE); convert(mid, max, value, list); } } private String base32Encode(final String str) { String unit = StringUtils.EMPTY_STRING; StringBuilder sb = new StringBuilder(); for (int start = 0; start < str.length(); start = start + 5) { unit = str.substring(start, start + 5); sb.append(base32Lookup[convertToIndex(unit)]); } return sb.toString(); } private int convertToIndex(String str) { int length = str.length(); int result = 0; for (int index = 0; index < length; index++) { result += str.charAt(index) == StringUtils.CHAR_ZERO ? 0 : 1 << (length - 1 - index); } return result; } public String encode(double lat, double lng) { List latList = new ArrayList(); List lngList = new ArrayList(); convert(Min_Lat, Max_Lat, lat, latList); convert(Min_Lng, Max_Lng, lng, lngList); StringBuilder sb = new StringBuilder(); for (int index = 0; index < latList.size(); index++) { sb.append(lngList.get(index)).append(latList.get(index)); } return base32Encode(sb.toString()); } public List around(double lat, double lng) { List list = new ArrayList(); list.add(encode(lat, lng)); list.add(encode(lat + latUnit, lng)); list.add(encode(lat - latUnit, lng)); list.add(encode(lat, lng + lngUnit)); list.add(encode(lat, lng - lngUnit)); list.add(encode(lat + latUnit, lng + lngUnit)); list.add(encode(lat + latUnit, lng - lngUnit)); list.add(encode(lat - latUnit, lng + lngUnit)); list.add(encode(lat - latUnit, lng - lngUnit)); return list; } }