第一种、根据经纬度进行计算,采用java编写
package com.xxxx.sentinel.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nick
*/
public class GeoHash {
public static final double MINLAT = -90;
public static final double MAXLAT = 90;
public static final double MINLNG = -180;
public static final double MAXLNG = 180;
public static final int ORIGINPRECISION = 30;
//经纬度二分法
private static List<Integer> latLng(double latAndLng, double min, double max) {
List<Integer> lngAndLatList = new ArrayList();
if (latAndLng < min || latAndLng > max) {
return null;
}
if (ORIGINPRECISION < 1) {
return null;
}
for (int i = 0; i < ORIGINPRECISION; i++) {
double mid = (min + max) / 2.0;
if (latAndLng > mid) {
lngAndLatList.add(1);
min = mid;
} else {
lngAndLatList.add(0);
max = mid;
}
}
return lngAndLatList;
}
public static void main(String[] args) {
//latLng(31.1688749, 121.3975184);
//将经纬度转成二分法
System.out.println(latLng(31.1688749,MINLAT,MAXLAT));
System.out.println(latLng(121.3975184,MINLNG,MAXLNG));
//合并经纬度
System.out.println(listToString(latLng(121.3975184,MINLNG,MAXLNG),latLng(31.1688749,MINLAT,MAXLAT)));
//二进制转成十进制,5个一组
System.out.println(twoTurnTen(listToString(latLng(121.3975184,MINLNG,MAXLNG),latLng(31.1688749,MINLAT,MAXLAT))));
//base32 映射
System.out.println(baseCode(twoTurnTen(listToString(latLng(121.3975184,MINLNG,MAXLNG),latLng(31.1688749,MINLAT,MAXLAT)))));
}
//偶数位放经度,奇数位放纬度
public static StringBuffer listToString(List<Integer> lngList, List<Integer> latList){
StringBuffer latAndLng = new StringBuffer();
for (int i = 0; i < ORIGINPRECISION; i++) {
latAndLng.append(lngList.get(i) * lngList.get(i));
latAndLng.append(latList.get(i) * latList.get(i));
}
return latAndLng;
}
//二进制转成十进制,5个一组
public static List<Integer> twoTurnTen(StringBuffer latAndLng){
List<Integer> code =new ArrayList<>();
int z = 0;
for(int i=0;i<latAndLng.length() / 5;i++){
String a = latAndLng.substring(z,z+5);
code.add(Integer.parseInt(a, 2));
z = z+5;
}
return code;
}
//base32 映射
public static StringBuffer baseCode(List<Integer> code){
Map<Integer,String> map = new HashMap<>(32);
map.put(0, "0");
map.put(1, "1");
map.put(2, "2");
map.put(3, "3");
map.put(4, "4");
map.put(5, "5");
map.put(6, "6");
map.put(7, "7");
map.put(8, "8");
map.put(9, "9");
map.put(10, "b");
map.put(11, "c");
map.put(12, "d");
map.put(13, "e");
map.put(14, "f");
map.put(15, "g");
map.put(16, "h");
map.put(17, "j");
map.put(18, "k");
map.put(19, "m");
map.put(20, "n");
map.put(21, "p");
map.put(22, "q");
map.put(23, "r");
map.put(24, "s");
map.put(25, "t");
map.put(26, "u");
map.put(27, "v");
map.put(28, "w");
map.put(29, "x");
map.put(30, "y");
map.put(31, "z");
StringBuffer stringBuffer = new StringBuffer();
for (Integer codes:code) {
if(map.keySet().contains(codes)){
stringBuffer.append(map.get(codes));
}
}
return stringBuffer;
}
}
第二种、根据redis的GEO实现
package com.xxxx.sentinel.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.List;
/**
* @author nick
*/
public class GeoHashRedis {
//################################
// Springboot redis 实现
//###############################
@Autowired
//操作k-v都是字符串的
StringRedisTemplate stringRedisTemplate;
/*@Autowired
RedisTemplate redisTemplate; //k-v都是对象的*/
@Autowired
RedisTemplate<Object, Object> redisTemplate;
//geoadd 添加地理位置
private void geoadd(double lat,double lng){
stringRedisTemplate.opsForGeo().add("geoTest",new Point(31.1688749, 121.3975184),"xxxx");
}
//geopos 查看位置信息
private void geopos(){
List<Point> position = stringRedisTemplate.opsForGeo().position("genoTest", "xxxx");
System.out.println(position);
}
//geodist 计算距离
private void geodist(){
}
//georadis 查看以某一点为中心,以某长度为半径的成员信息
private void georadis(){
}
//geohash计算geohash值
private void geohash(){
stringRedisTemplate.opsForGeo().hash("geoTest","xxxx");
}
//############################################################
// jedis 实现
//############################################################
/**
* 增加地理位置的坐标
* @param key
* @param coordinate
* @param memberName
* @return
*/
public static Long geoadd(String key, GeoCoordinate coordinate, String memberName) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.geoadd(key,coordinate.getLongitude(),coordinate.getLatitude(),memberName);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis)
jedis.close();
}
return null;
}
/**
* 批量添加地理位置
* @param key
* @param memberCoordinateMap
* @return
*/
public static Long geoadd(String key, Map<String, GeoCoordinate> memberCoordinateMap){
RedisProperties.Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.geoadd(key, memberCoordinateMap);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis) {
jedis.close();
}
}
return null;
}
/**
* 根据给定地理位置坐标获取指定范围内的地理位置集合(返回匹配位置的经纬度 + 匹配位置与给定地理位置的距离 + 从近到远排序,)
* @param key
* @param coordinate
* @param radius
* @return List<GeoRadiusResponse>
*/
public static List<GeoRadiusResponse> geoRadius(String key, GeoCoordinate coordinate, double radius) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.georadius(key, coordinate.getLongitude(), coordinate.getLatitude(), radius, GeoUnit.KM, GeoRadiusParam.geoRadiusParam().withDist().withCoord().sortAscending());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis)
jedis.close();
}
return null;
}
/**
* 根据给定地理位置获取指定范围内的地理位置集合(返回匹配位置的经纬度 + 匹配位置与给定地理位置的距离 + 从近到远排序,)
* @param key
* @param member
* @param radius
* @return List<GeoRadiusResponse>
*/
List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.georadiusByMember(key, member, radius, GeoUnit.KM, GeoRadiusParam.geoRadiusParam().withDist().withCoord().sortAscending());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis)
jedis.close();
}
return null;
}
/**
* 查询两位置距离
* @param key
* @param member1
* @param member2
* @param unit
* @return
*/
public static Double geoDist(String key, String member1, String member2, GeoUnit unit){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.geodist(key, member1, member2, unit);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis)
jedis.close();
}
return null;
}
/**
* 可以获取某个地理位置的geohash值
* @param key
* @param members
* @return
*/
public static List<String> geohash(String key, String... members){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.geohash(key, members);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis)
jedis.close();
}
return null;
}
/**
* 获取地理位置的坐标
* @param key
* @param members
* @return
*/
public static List<GeoCoordinate> geopos(String key, String... members){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
return jedis.geopos(key, members);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
if (null != jedis) {
jedis.close();
}
}
return null;
}
}
参考:https://zhuanlan.zhihu.com/p/90889887
参考:https://blog.csdn.net/xiangnan10/article/details/80225929