java 地图四色着色算法_o2o附近的商家功能常见的算法:geohash和spatial4j调试实战...

本文介绍了如何使用GeoHash和Spatial4j实现O2O应用中查询附近商家的功能。通过调试GeoHash算法和Spatial4j工具,详细阐述了查询附近1km范围内的数据方法,包括处理GeoHash的边界误差问题。此外,还提到了其他调试的开源项目。
摘要由CSDN通过智能技术生成

开篇

我调试了很多开源项目,包括开源商城、IM即时通讯等很多,感兴趣的可以看看源码点我头像进去,觉得有用给个关注吧。

最近在看o2o相关的原理,网上说了很多geohash算法的原理。但其实原理网上有很多,但真正的调试少之又少,今天就来写代码调试一下geo算法和spatial4工具j。轻松实现,附近的商家功能。觉得有用,就点个赞转个发吧。看文章的时候最好是跟着做,如果没时间就收藏转发吧。

c18c09e5bf360ff60a7124afa1148bc5.png

geohash算法原理简单介绍

geo 是地理位置的geography 的缩写,hash其实就是hash算法。大家都知道,我们平常用的百度地图,高德地图其实每一个点都是有经纬度的。你可以理解为geohash,其实就是经纬度经过一些列运算出来的hash值,相似的经纬度得到的geohash值前缀几乎一致,这样就可以把一个区域内的点都可以直接在数据库中查出来,当然具体原理自己可以去搜索。这里就不介绍了,今天重点介绍,如何使用。

源码可以到github上看:https://github.com/kungfoo/geohash-java

22f0814add5547c1ddab036f9d9ad7e0.png

spatial4j工具

其实地球是球形的大家都知道,但基本上在地图上你可以认为是平面。例如查询附近1km的范围你怎么查呢?给定圆心坐标和半径,求该圆外切正方形四个顶点的坐标。不是吗?这个计算我们就用到spatial4j了。github上的地址是:https://github.com/locationtech/spatial4j

701d9ff5967dd818cf5788ec791592f0.png

核心调试

1、建表,建工程

新建一个spring boot 工程,集成mybatis等,当然建个商户表,有商户名称,经纬度,geohash等字段。

CREATE TABLE `merchant` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `merchant_name` VARCHAR(64) NOT NULL COMMENT '名称', `longitude` DOUBLE(9,6) NOT NULL COMMENT '经度', `latitude` DOUBLE(8,6) NOT NULL COMMENT '纬度', `geo_code` CHAR(12) NOT NULL COMMENT 'geohash编码', PRIMARY KEY (`id`),KEY `idx_merchant_longitude_latitude` (`longitude`,`latitude`), KEY `idx_merchant_geo_code` (`geo_code`))COMMENT='商户表' CHARSET=utf8mb4 ENGINE=InnoDB;
e2eea2daae5216b9e2c8399ff13a1bc9.png

2、方法一、查询附近的1km的用spatial4j实现

A、首先引入jar包:

 com.spatial4j spatial4j 0.5
caba9552c0afb75dca9b37a4b50051dc.png

B、计算四个点的的值

public static void main(String[] args) { //起始点经纬度 double lon = 116.312528, lat = 39.983733; // 千米 int radius = 1; SpatialContext geo = SpatialContext.GEO; Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt( geo.makePoint(lon, lat),  radius * DistanceUtils.KM_TO_DEG, geo, null); System.out.println(rectangle.getMinX() +  "-" + rectangle.getMaxX());// 经度范围 System.out.println(rectangle.getMinY() +  "-" + rectangle.getMaxY());// 纬度范围 }
23378df742bff1b7c639e5714e67d9b0.png

C、根据范围,在数据库中查找即可,查到附近1km的数据。当然,经纬度最好做联合索引。这两个数据是上面算出来的。

SELECT id, merchant_nameFROM merchantWHERE (longitude BETWEEN ? AND ?) AND (latitude BETWEEN ? AND ?);

3、根据geohash查询。此时会用到geo_code 字段。

A、引入geohash的jar包

ch.hsr geohash 1.3.0
29b57f9dd24ec7309984a32498c33ff3.png

B、对照geohash的长度对应范围表,我们可以知道,查询附近1km的数据,只要长度是5就可以了。具体计算,GeohashUtils.encodeLatLon(lat, lon, 5),代入底线sql即可。

SELECT id, merchant_nameFROM merchantWHERE geo_code LIKE CONCAT(?, '%');
d077f63c2b4a25c376841f4773fd3075.png

C、但geohash有边界问题误差。因为geohash是某个区域的共同的hash,索引边界以外的距离很近的点可能造成geohash完全不同,那么怎么办呢?其实也不难解决,你这个时候把周围的八个区域的geohash都算出来即可。

public static void main(String[] args) { // 移动设备经纬度 double lon = 116.312528, lat = 39.983733; GeoHash geoHash = GeoHash. withCharacterPrecision (lat, lon, 6); // 当前 System.out.println(geoHash.toBase32()); // N, NE, E, SE, S, SW, W, NW System.out.println("---------------------------"); //东南西北,东北、西北、东南、西南等 GeoHash[] adjacent = geoHash.getAdjacent(); for (GeoHash hash : adjacent) { System.out.println(hash.toBase32()); } }
22f0814add5547c1ddab036f9d9ad7e0.png
72822215356bd008670a11460a675c9f.png

D、mysql查询,查询出这几个区域的商家即可,geohash边界问题就可以解决。

SELECT id, merchant_nameFROM merchantWHERE geo_code IN (?, ?, ?, ?, ?, ?, ?, ?, ?);

结语

o2o中最常见的应用场景就是附近的商家,希望此篇文章对于o2o的同学有些帮助。觉得有用就点个赞转发一下吧。

另外我还调试了其他很多开源项目

Java 开源的基于微服务 Spring cloud 快速开发脚手架调试实战

超好用的 Java 开源 验证码 神器

Java 搭建的开源的spring boot商城系统实战

前后端分离的开源在线考试系统调试实战

调试个开源Java 轻量级高性能IM,单机支持几十万至百万在线用户

Java 百分之百开源 CMS 系统项目调试实战

前端牛人写的开源的CMS系统调试实战,流体布局兼容手机端浏览器

觉得有用可以给个关注哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值