redis geohash java 及spatial4j计算距离

redis3.2版本提供了geohash功能
geohash的原理参考geohash精度与原理

求两个坐标之间的距离
    使用geoadd命令添加两个坐标的经纬度
    使用geodist命令获取两个坐标的距离

    jedis代码如下

    参数说明:geoadd中第一个参数geoKey表示一个地理位置的集合、第二与第三个参数是某个坐标的经度与纬度,第三个参数表示与该坐标唯一对应的member

    private JedisPool pool = new JedisPool("192.168.92.128",6380);
    
    @Test
    public void testJedisGeoDistance(){
        Jedis jedis = pool.getResource();
        double beijingLon = 116.20;
        double beijingLat = 39.56;

        double shanghaiLon = 120.51;
        double shanghaiLat = 30.40;
        String geoKey = UUID.randomUUID().toString();
        jedis.geoadd(geoKey,beijingLon,beijingLat,"beijing");
        jedis.geoadd(geoKey,shanghaiLon,shanghaiLat,"shanghai");
        double distance = jedis.geodist("geoHashDistance","beijing","shanghai", GeoUnit.KM);
        System.out.println(distance);

    }

    spring-data-redis代码如下

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Test
    public void testSpringDataRedisGeoDistance(){
        Point beijing = new Point(116.20,39.56);
        Point shanghai = new Point(120.51,30.40);
        String geoKey = UUID.randomUUID().toString();
        redisTemplate.opsForGeo().add(geoKey,beijing,"beijing");
        redisTemplate.opsForGeo().add(geoKey,shanghai,"shanghai");
        Distance distance = redisTemplate.opsForGeo().distance(geoKey, "beijing", "shanghai", Metrics.KILOMETERS);
        System.out.println(distance.getValue());
    }

获取某一个或多个坐标的geohash编码(redis只精确到第十一位)

       

    @Test
    public void testGeoHash(){
        Jedis jedis = pool.getResource();
        double beijingLon = 116.20;
        double beijingLat = 39.56;
        String geoKey = UUID.randomUUID().toString();
        jedis.geoadd(geoKey,beijingLon,beijingLat,"beijing");
        String geoHash = jedis.geohash(geoKey,"beijing").get(0);
        //spring-data-redis 获取坐标的geohash编码
//        redisTemplate.opsForGeo().hash(geoKey,"beijing");
        System.out.println(geoHash);
    }

获取某一点附近的坐标(使用radius或radiusMember方法)

    @Test
    public void testRadius(){
        Point beijing = new Point(116.20,39.56);
        Point shanghai = new Point(120.51,30.40);
        Point myPoint = new Point(112.36,29.70);
        String geoKey = UUID.randomUUID().toString();
        redisTemplate.opsForGeo().add(geoKey,beijing,"beijing");
        redisTemplate.opsForGeo().add(geoKey,shanghai,"shanghai");
        redisTemplate.opsForGeo().add(geoKey,myPoint,"mypoint");
        Distance distance = new Distance(1000,Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs param = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending();
        GeoResults<RedisGeoCommands.GeoLocation<String>> results =  redisTemplate.opsForGeo().radius(geoKey,"mypoint",distance,param);
        results.getContent().forEach(new Consumer<GeoResult<RedisGeoCommands.GeoLocation<String>>>() {
            @Override
            public void accept(GeoResult<RedisGeoCommands.GeoLocation<String>> geoLocationGeoResult) {
                System.out.println(geoLocationGeoResult.getContent().getName() + " : " + geoLocationGeoResult.getDistance().getValue());
            }
        });
        //使用jedis
//        Jedis jedis = pool.getResource();
//        GeoRadiusParam param = GeoRadiusParam.geoRadiusParam().withHash().withDist().withCoord().sortAscending();
//        List<GeoRadiusResponse> list = jedis.georadiusByMember(geoKey,"mypoint",1000,GeoUnit.KM,param);
//        System.out.println(list);
    }

使用spatial4j计算两点之间的距离

导入依赖

<dependency>
      <groupId>org.locationtech.spatial4j</groupId>
      <artifactId>spatial4j</artifactId>
      <version>0.8</version>
    </dependency>
    private static SpatialContext geo = SpatialContext.GEO;

    @Test
    public void testSpatial4J(){
        org.locationtech.spatial4j.shape.Point point = new PointImpl(116.20,39.56,geo);
        org.locationtech.spatial4j.shape.Point point1 = new PointImpl(120.51,30.40,geo);
        double distance = geo.calcDistance(point,point1) * DistanceUtils.DEG_TO_KM;
        System.out.println(distance);
    }

注意geo.calcDistance(point,point1)得到的是两点之间的度数,两点之间的距离=度数乘以DistanceUtils.DEG_TO_KM

Spatail4j获取坐标的geohash编码(参数12表示geohash码精确到第12位)

    @Test
    public void testSpatial4JGeoHash(){
        String geoHash = GeohashUtils.encodeLatLon(39.56,116.2,12);
        System.out.println(geoHash);
    }

猜你喜欢

转载自blog.csdn.net/name_is_wl/article/details/113572207