postgis 中的距离计算
最近在做一个项目,有一个功能想要实现类似于查询附近的人的功能。由于项目的原因数据库只能使用 postgresql,空间查询就使用了 postgis 来实现。
具体业务像这样:业务需要返回附近距自己 1000 米的人的一个列表,返回列表中要带上距离,就是说某人距你多少米?
使用定位方式是什么?
我们使用 gps 定位发现定位精度,时间,误差和抖动都需要发大量的时间去处理。
于是采用了百度的定位 SDK,百度的上面几处都处理不错。
有一个小问题,从百度拿到的坐标是 经度和纬度,这个坐标系应该是地理坐标,由于也是使用 gps ,其基础坐标应该是 wgs84。所以拿到的值应该是:wgs84 + 国家偏移 + 百度偏移 = 百度坐标
后面两项是没有太好的办法解决,我们拿百度坐标与 google 的大致对比了一下,误差 50 米以内,业务可以接受。
而且这个后面两项是系统偏移,不是随机的,这样的话,计算距离这种相对计算,应该可以消除部分系统偏移的影响。
再说说postgis 计算距离
postgis 是一个地理空间查询引擎,计算地理距离这很方便。
- 开始我们在表中建一列用于存地理类型的
geometry。
SELECT AddGeometryColumn ('public','chest','position',4326,'POINT',2, false);
- 然后保存的时候,将 经纬度和 经纬度变成
geometry进行保存,也就是三个字段,其中保存geometry是用下面的sql:
ST_GeomFromText('POINT(${lng} ${lat})', 4326)
sql 中的 4326 是指的wsg84 的系统。
- 然后对保存后的值进行距离查询,使用
ST_distance进行,后面有二个坑等着我们:
第一个:geometry 的问题
postgis 中 geomery 使用 ST_distance 计算出来的单位竟然是弧度,不是 米,找了一段时间问题,发现是没有使用投影坐标引起的。
于是在计算的时候,先将 点 变成 投影坐标,再来计算。
ST_Transform(geo, 2346)
这里的 2346 是中国西安 80 高斯克里格投影的编号,是分带的,使用的中央经线在南京。
加上这个,我们能正确计算出来距离,也是 米。
然后,一段时间后,把应用发到别的城市,也就是苏州,出现了问题
第二个: 投影带号的问题
原因是苏州不在 2346 中的带号里面,计算就出错了!
这样就有问题了,全国这么多的带号,不可能写在程序里,动态计算啊?再说万一出国了,没有中国的投影怎么办?
回头再去找方案,这个计算距离应该要支持最低就是全国,最好是全世界。
还真找到了,就是 geography。
解释一下: geography 和 geometry 都是 postgis 中的数据类型,翻绎过来:地理图形和几何图形,用 postgis 的说法就是, geography 就是使用 wgs84 坐标系 的图形。
postgis 可以直接使用 geography 进行计算,支持全球。于是这个问题,终于有解决方案了,就是把我们的 geometry 转成 geography ,然后进行距离计算。
下面是我们使用 sql 语句
select
(ST_distance(position::geography, ST_GeomFromText('POINT(121 32)', 4326)::geography) as distance
from chest
where ST_dwithin(position::geography, ST_GeomFromText('POINT(121 32})', 4326)::geography, 1000)
orderBy distance desc
其中:position 是我存在数据库中的字段,使用的是 geometry 的类型, (121,32 )是我输入的中心点。
::geography 就是postgis 中的 转换类型语法,把 geometry 转成 geography,然后计算,这样全球都能使用。
总结
这些问题的解决,算是把以前的知识在复习了一下。 在项目中,我们也可以直接把坐标存成 geography,使用如下的 sql:
ST_GeographyFromText('SRID=4326;POINT(-110 30)')
数据就不用转来转去了。
只是项目已有数据,不能这样做了。
参考文档
postgis 中的距离计算的更多相关文章
- [转] MachingLearning中的距离相似性计算以及python实现
参考:https://blog.csdn.net/gamer_gyt/article/details/75165842#t16 https://blog.csdn.net/ymlgrss/artic ...
- 你真的会用PostGIS中的buffer缓冲吗?
buffer - 图形缓冲区分析,GIS中最基本的空间分析之一. 实现buffer的工具有很多种,例如前端的truf.js.服务端的ArcGISserver.桌面端的ArcMap.数据库端的PosrG ...
- 管道设计CAD系统中重量重心计算
管道设计CAD系统中重量重心计算 eryar@163.com Abstract. 管道设计CAD系统中都有涉及到重量重心计算的功能,这个功能得到的重心数据主要用于托盘式造船时方便根据重心设置吊装配件. ...
- Scipy教程 - 距离计算库scipy.spatial.distance
http://blog.csdn.net/pipisorry/article/details/48814183 在scipy.spatial中最重要的模块应该就是距离计算模块distance了. fr ...
- Touch事件详解及区别,触屏滑动距离计算
移动端有四个关于触摸的事件,分别是touchstart.touchmove.touchend.touchcancel(比较少用), 它们的触发顺序是touchstart-->touchmove- ...
- 相似度与距离计算python代码实现
#定义几种距离计算函数 #更高效的方式为把得分向量化之后使用scipy中定义的distance方法 from math import sqrt def euclidean_dis(rating1, r ...
- 通过经纬度坐标计算距离的方法(经纬度距离计算)ZZ
通过经纬度坐标计算距离的方法(经纬度距离计算) 最近在网上搜索“通过经纬度坐标计算距离的方法”,发现网上大部分都是如下的代码: #define PI 3.14159265 static double ...
- V-rep学习笔记:碰撞检测与距离计算
V-REP可以在几何组件中快速判断各种干扰与碰撞,以及计算多个组件间的最小距离. 碰撞检测 V-REP可以检测两个碰撞体实体(Collidable objects are objects that c ...
- 基于js利用经纬度进行两地的距离计算(转)
转自:http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation- ...
随机推荐
- VirtulBox虚拟机搭建Linux Centos系统
简要说明 该文章目的是基于搭建hadoop的前置文章,当然也可以搭建Linux的入门文章.那我再重复一下安装准备软件. 环境准备:http://pan.baidu.com/s/1dFrHyxV 密码 ...
- 576. Out of Boundary Paths
Problem statement: There is an m by n grid with a ball. Given the start coordinate (i,j) of the ball ...
- 微信创建带参数二维码并加上logo
1.因为带参数二维码有两种,分别是字符参数,数值参数,因此,在写创建方法的时候,需要进行判断 public void ShowQcCode(N_WX_QrCode code) { QRCodeCrea ...
- poj 1321 棋盘问题 简单DFS
题目链接:http://poj.org/problem?id=1321 很久没有敲搜索了啊,今天敲了个水题练练手,哈哈.... 题目大意: 就是求在n*n的方格上放置k个棋子的方案数 代码: #inc ...
- 每天一道Java题[2]
问题 可以直接根据hashCode()方法产生的值判断两个对象是否相等吗? 解答 不能!根据Wikipedia(https://en.wikipedia.org/wiki/Java_hashCode( ...
- 看完48秒动画,让你不敢再登录HTTP网站(附完整示例代码)
在我的 单点登录SSO示例代码 一文中,强烈不建议部署HTTP的SSO服务站点. 在此写个基于网络包嗅探的HTTP会话劫持程序,给大家一个直观的危害性展示. 示例中,我在一台Mac上登录58同城,被另 ...
- 预览github项目的html文件新方法
原文地址:→看过来 写在前面 关于如何在线预览github中的html文件,其实这是一个很多人知道的东西,但是查资料的时候呢总是找不到正确的答案,并且一开始我也是踩了坑的. 踩坑经历 搜出来的结果大概 ...
- C#超简单方法实现两个richtextbox控件滚动条同步滚动
此文章属于作者原创,转载请注明,谢谢 有时候我们需要实现对照文章等,往往将文本放到两个richtextbox控件中,但是,如果我们需要同步滚动查看,来达到更好的观看效果. 当然,传统的方法重载控件或者 ...
- Spring切面编程步骤
什么是面向切面编程 面向对象的编程主要注重核心业务,而面向切面编程主要关注一些不是核心的业务,但又是必须的辅助功能,比如一个完整的系统中,记录平时系统运行时抛出的异常,需要我们去记录,以便我们对系统尽 ...
- javaWeb学习总结(8)- jsp指令(3)
一.JSP指令简介 一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定 ...