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- ...
随机推荐
- javascript函数作用域及this指向详解
一.先说一个简单的概念--变量提升: 通过function+函数名的方式,声明的函数,可以在代码中的任何位置调用: 通过var定义变量的方式,声明的函数,则必须在声明之后进行调用,原因就是在变量定义之 ...
- Windows安装Mysql5.7.10绿色版
今天在Windows上安装Mysql的时候,去官网上下了一个最新版本的Mysql5.7.10绿色版,但是之前网上安装方式都过时了,比如会报一些常见的错误“[ERROR] Fatal error: Ca ...
- DelayQueue的原理和使用浅谈
在谈到DelayQueue的使用和原理的时候,我们首先介绍一下DelayQueue,DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素.该队列的头部是延迟期满后保存时间最长的De ...
- z-Tree-checkbox
引入z-Tree css/js/不要忘记excheck.js //html部分 <div> <input type="text" v-model="b ...
- 【转】纯手工玩转 Nginx 日志
Nginx 日志对于大部分人来说是个未被发掘的宝藏,总结之前做某日志分析系统的经验,和大家分享一下 Nginx 日志的纯手工分析方式. Nginx 日志相关配置有 2 个地方:access_log 和 ...
- Go - Struct
定义 go 语言中的struct与c的很相似,此外,go没有Class,也没有继承. stuct的格式为:type <name> struct{} package main import ...
- IPv6,AppStore 审核不是唯一选择它的原因
为什么选择 IPv6?因为更快的 InternetIPv6 更快有两个原因.第一点,像 iOS.MacOS.Chrome 和 Firefox 这样的主流的操作系统或者浏览器,在它们使用 IPv4 连接 ...
- Windows 自动获取IP脚本
@echo off echo 正在自动获取IP地址.... set 连接名称=以太网 netsh interface ip set address name = "%连接名称%" ...
- 《算法4》1.5 - Union-Find 算法解决动态连通性问题,Python实现
Union-Find 算法(中文称并查集算法)是解决动态连通性(Dynamic Conectivity)问题的一种算法,作者以此为实例,讲述了如何分析和改进算法,本节涉及三个算法实现,分别是Quick ...
- 使用redis做mybaties的二级缓存(2)-Mybatis 二级缓存小心使用
Mybatis默认对二级缓存是关闭的,一级缓存默认开启: 下面就说说为什么使用二级缓存需要注意: 二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到 ...