package com.walker.location;
|
|
import com.walker.infrastructure.utils.StringUtils;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* 计算GeoHash工具类,该对象可创建单例。
|
* <pre>
|
* 1 = 2500km;
|
* 2 = 630km;
|
* 3 = 78km;
|
* 4 = 30km;
|
* 5 = 2.4km;
|
* 6 = 610m;
|
* 7 = 76m;
|
* 8 = 19m;
|
* </pre>
|
* @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<Character> 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<Character> latList = new ArrayList<Character>();
|
List<Character> lngList = new ArrayList<Character>();
|
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<String> around(double lat, double lng) {
|
List<String> list = new ArrayList<String>();
|
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;
|
}
|
}
|