Geohash之范围搜索
概述
很多时候,我们都会遇到这样的需求:查找某个点周边多少距离的点。从本质来说,是一个缓冲区分析+空间查找,本文结合Geohash来实现类似的功能。
效果
说明:
- 红色的点和红色的圈是查找的中心点和距离(5km);
- 蓝色的点+粉色的点是通过geohash查找出来的点;
- 粉色的点是通过过滤后的点;
实现
本文实现是结合sqlite数据库实现的,实现的思路如下:
1. 数据的初始化
本示例所用的数据源于网络下载下来的shp数据,并做了解析入库,表结构如下:
CREATE TABLE "geocode_point"
(id NVARCHAR(50) PRIMARY KEY NOT NULL,poiname NVARCHAR(200),x NUMERIC,y NUMERIC,minzoom INTEGER(2),maxzoom INTEGER(2)
, geohash NVARCHAR(20) NULL)
2. 根据geohash查找点
根据查找的距离范围,先获取geohash的位数,实现方法如下:
/*** 获取距离有效位数* @param radius* @return*/public int effectnum(double radius){int result = 0;if (radius <= 0) result = 0;else if (radius < 1) result = 10;else if (radius < 5) result = 9;else if (radius < 20) result = 8;else if (radius < 77) result = 7;else if (radius < 610) result = 6;else if (radius < 2400) result = 5;else if (radius < 20000) result = 4;else if (radius < 78000) result = 3;else if (radius < 630000) result = 2;else result = 0;return result;}
再查找前面的值相同的记录,实现代码如下:
int precision = geoHash.effectnum(dist);
String strGeohash = geoHash.encode(lat, lon, 0);
String filters = "where geohash like '"+strGeohash.substring(0, precision)+"%'";
List _list = geoDao.getDataByFilter(points.getTableName(), points.getTableFields(), filters, new Object[]{});
3. 计算满足条件的点
由于是经纬度的数据,所以在计算两点距离的时候进行了坐标转换,将经纬度转换为了Web墨卡托,此举是结合geotools实现的。
1)坐标转换
public double[] lonlat2WebMactor(double lon, double lat){Point geom =new GeometryFactory().createPoint(new Coordinate(lon, lat));try{CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");// 投影转换MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);Point webPoint = (Point)JTS.transform(geom, transform);return new double[]{webPoint.getX(), webPoint.getY()};}catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();return null;}}
2)计算距离
public double distance(String geohash1, String geohash2){Map lonlat1 = decode(geohash1),lonlat2 = decode(geohash2);double lat1 = (Double) lonlat1.get("lat"),lon1 = (Double) lonlat1.get("lon");double lat2 = (Double) lonlat2.get("lat"),lon2 = (Double) lonlat2.get("lon");double[] webPoint1 = lonlat2WebMactor(lon1, lat1),webPoint2 = lonlat2WebMactor(lon2, lat2);return Math.sqrt(Math.pow(webPoint1[0]-webPoint2[0], 2d)+Math.pow(webPoint1[1]-webPoint2[1], 2d));};
3)筛选满足条件的点
将查询出来的结果做比较,筛选满足条件的点。
for(int i=0;i<_list.size();i++){Map map = (Map)_list.get(i);String _geohash = map.get("geohash").toString();double _dist = geoHash.distance(strGeohash, _geohash);if(_dist<dist)list.add(map);}return list;
将2和3串起来,实现代码如下:
public List searchByDist(double lon, double lat, double dist){List list = new ArrayList();int precision = geoHash.effectnum(dist);String strGeohash = geoHash.encode(lat, lon, 0);String filters = "where geohash like '"+strGeohash.substring(0, precision)+"%'";List _list = geoDao.getDataByFilter(points.getTableName(), points.getTableFields(), filters, new Object[]{});System.out.println(JSONArray.toJSONString(_list));for(int i=0;i<_list.size();i++){Map map = (Map)_list.get(i);String _geohash = map.get("geohash").toString();double _dist = geoHash.distance(strGeohash, _geohash);if(_dist<dist)list.add(map);}return list;}
技术博客
CSDN:http://blog.csdn.NET/gisshixisheng
博客园:http://www.cnblogs.com/lzugis/
在线教程
http://edu.csdn.Net/course/detail/799
Github
https://github.com/lzugis/
联系方式
类型 | 内容 |
---|---|
1004740957 | |
公众号 | lzugis15 |
niujp08@qq.com | |
webgis群 | 1004740957 |
Android群 | 337469080 |
GIS数据可视化群 | 458292378 |
Geohash之范围搜索相关推荐
- geohash地图好帮手
正经学徒,佛系记录,不搞事情 详细的解释交给专业的大佬,我就用用: 来自大佬的详解 geohash的距离估算 工具类: 包含坐标和geohash的转换:查询geohash周围九格的geohash ...
- 仿elem页面学习之表单提交的动作
接上篇 仿elem页面学习之input type=search 搜索地址 当我们在input输入框输入地址,有时候可以不记得准确的店名或地址,这时候我们希望软件能根据搜索关键词给出一些相近的推荐,如上 ...
- redis-GEO地理位置
Redis 3.2版本一个重大的更新是新增了GEO地理位置相关的命令. 目前Redis对地理位置支持提供了一下6个命令: 1. geoadd: 增加地理位置的坐标. 2. geodist: 获取两个地 ...
- 【独家直播】 德哥PG系列课程15讲—PostgreSQL 多场景 沙箱实验从入门到精通
简介 标签:PostgreSQL , 沙箱 , 实验 背景:为了能够让用户可以更快的上手PostgreSQL,德哥与云栖团队的小伙伴制作了一系列阿里云RDS PostgreSQL沙箱实验.所有实验内容 ...
- geohash 附近搜索
2019独角兽企业重金招聘Python工程师标准>>> 附近搜索 geohash.neighbors 生成周边8个geohash(如下图),生成的长方形区域,与我要的搜索附近半径几公 ...
- geohash美团附近酒店搜索-技术方案
美团附近酒店搜索-技术方案 自Redis 3.2开始,Redis基于geohash和zset提供了地理位置相关功能. 什么是Geohash Geohash是一种地址编码,它能把二维的经纬度编码成一维的 ...
- Redis核心数据结构ZSET、GeoHash 、 Stream--排行榜、消息Pull推送、附近搜索、布隆过滤器 、IM聊天室
ZSET.Geo . Stream redis zset数据结构 常用命令 排行榜 步骤一.初始化1个月的历史数据 步骤二:定时刷新数据 步骤3:排行榜查询接口 GeoHash 命令 附近酒店搜索实现 ...
- 算法进阶系列1 空间搜索 GeoHash 算法
1. 背景 我们经常会用到 App 打车和共享单车,App 界面上会显示出自己附近一个范围内可用的出租车或者共享单车: 那如何发现以自己为圆心一定范围内的车呢?最直观的想法就是在数据库里存储每一辆车的 ...
- Query理解在美团搜索中的应用
分享嘉宾:刘亮 美团 资深算法工程师 编辑整理:吴雪松 出品社区:DataFunTalk 导读:在过去的20年中,搜索过程中处理查询的方式以及向用户显示结果的方式已完全改变.该过程已经从仅基于文本匹配 ...
最新文章
- IOS - 快速入门
- 【AtCoder】AGC017
- 天池 在线编程 布尔表达式求值(栈)
- mysql goldengate_goldengate同步mysql
- python输入数组_python怎么输入数组
- CMakeLists.txt的语法介绍和几个实例
- java graphics dispose_Graphics.Dispose 方法 (System.Drawing) | Microsoft Docs
- ADO.Net之SqlConnection、 Sqlcommand的应用
- 【Knowledge Fragment】
- Ka的回溯编程练习 Part4|分配工作与选书
- 使用代码辅助生成工具CodeSmith -- 生成NHibernate的映射文件
- 汇率换算(android安卓版)
- iOS中 断点下载详解
- C语言读取文件时txt中的汉字出现乱码的解决方案
- 安卓APP源码和设计报告——基于Android的垃圾分类系统
- android 判断 音乐是否播放,Android如何判断当前手机是否正在播放音乐并获取有关正在播放的音乐的信息...
- Opencv各版本汇总下载
- 使用Button(按钮)
- 微软Windows系统发展史
- 【STM32篇】4988驱动步进电机
热门文章
- 华为Nova3e HL1ANNEM手机图纸-电路原理图纸
- HD4600 核显 黑苹果升级10.14.1 出现部分软件花屏解决方法
- Matlab2018a 与ccs7生成tms320F2812代码调试记录
- php爬虫抓取信息及反爬虫相关
- 解决修改hosts文件权限不够的问题
- ONVIF协议网络摄像机(IPC)客户端程序开发使用gSOAP生成ONVIF框架代码(C++)03-->Windows
- 超详细的log4j的配置和使用
- PDF的简单应用查找、保存、查看
- 开发工具:2022个人开发工具清单
- Android实现圆形图片