最近在做一个项目,有一个功能想要实现类似于查询附近的人的功能。由于项目的原因数据库只能使用 postgresql,空间查询就使用了 postgis 来实现。

具体业务像这样:业务需要返回附近距自己 1000 米的人的一个列表,返回列表中要带上距离,就是说某人距你多少米?

使用定位方式是什么?

我们使用 gps 定位发现定位精度,时间,误差和抖动都需要发大量的时间去处理。

于是采用了百度的定位 SDK,百度的上面几处都处理不错。

有一个小问题,从百度拿到的坐标是 经度和纬度,这个坐标系应该是地理坐标,由于也是使用 gps ,其基础坐标应该是 wgs84。所以拿到的值应该是:wgs84 + 国家偏移 + 百度偏移 = 百度坐标

后面两项是没有太好的办法解决,我们拿百度坐标与 google 的大致对比了一下,误差 50 米以内,业务可以接受。

而且这个后面两项是系统偏移,不是随机的,这样的话,计算距离这种相对计算,应该可以消除部分系统偏移的影响。

再说说postgis 计算距离

postgis 是一个地理空间查询引擎,计算地理距离这很方便。

  1. 开始我们在表中建一列用于存地理类型的 geometry
SELECT AddGeometryColumn ('public','chest','position',4326,'POINT',2, false);
  1. 然后保存的时候,将 经纬度和 经纬度变成 geometry 进行保存,也就是三个字段,其中保存 geometry 是用下面的sql
ST_GeomFromText('POINT(${lng} ${lat})', 4326)

sql 中的 4326 是指的wsg84 的系统。

  1. 然后对保存后的值进行距离查询,使用 ST_distance 进行,后面有二个坑等着我们:

第一个:geometry 的问题

postgisgeomery 使用 ST_distance 计算出来的单位竟然是弧度,不是 ,找了一段时间问题,发现是没有使用投影坐标引起的。

于是在计算的时候,先将 变成 投影坐标,再来计算。

ST_Transform(geo, 2346)

这里的 2346中国西安 80 高斯克里格投影的编号,是分带的,使用的中央经线在南京。

加上这个,我们能正确计算出来距离,也是

然后,一段时间后,把应用发到别的城市,也就是苏州,出现了问题

第二个: 投影带号的问题

原因是苏州不在 2346 中的带号里面,计算就出错了!

这样就有问题了,全国这么多的带号,不可能写在程序里,动态计算啊?再说万一出国了,没有中国的投影怎么办?

回头再去找方案,这个计算距离应该要支持最低就是全国,最好是全世界。

还真找到了,就是 geography

解释一下: geographygeometry 都是 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-04.md

Geography

postgis 中的距离计算的更多相关文章

  1. [转] MachingLearning中的距离相似性计算以及python实现

    参考:https://blog.csdn.net/gamer_gyt/article/details/75165842#t16  https://blog.csdn.net/ymlgrss/artic ...

  2. 你真的会用PostGIS中的buffer缓冲吗?

    buffer - 图形缓冲区分析,GIS中最基本的空间分析之一. 实现buffer的工具有很多种,例如前端的truf.js.服务端的ArcGISserver.桌面端的ArcMap.数据库端的PosrG ...

  3. 管道设计CAD系统中重量重心计算

    管道设计CAD系统中重量重心计算 eryar@163.com Abstract. 管道设计CAD系统中都有涉及到重量重心计算的功能,这个功能得到的重心数据主要用于托盘式造船时方便根据重心设置吊装配件. ...

  4. Scipy教程 - 距离计算库scipy.spatial.distance

    http://blog.csdn.net/pipisorry/article/details/48814183 在scipy.spatial中最重要的模块应该就是距离计算模块distance了. fr ...

  5. Touch事件详解及区别,触屏滑动距离计算

    移动端有四个关于触摸的事件,分别是touchstart.touchmove.touchend.touchcancel(比较少用), 它们的触发顺序是touchstart-->touchmove- ...

  6. 相似度与距离计算python代码实现

    #定义几种距离计算函数 #更高效的方式为把得分向量化之后使用scipy中定义的distance方法 from math import sqrt def euclidean_dis(rating1, r ...

  7. 通过经纬度坐标计算距离的方法(经纬度距离计算)ZZ

    通过经纬度坐标计算距离的方法(经纬度距离计算) 最近在网上搜索“通过经纬度坐标计算距离的方法”,发现网上大部分都是如下的代码: #define PI 3.14159265 static double ...

  8. V-rep学习笔记:碰撞检测与距离计算

    V-REP可以在几何组件中快速判断各种干扰与碰撞,以及计算多个组件间的最小距离. 碰撞检测 V-REP可以检测两个碰撞体实体(Collidable objects are objects that c ...

  9. 基于js利用经纬度进行两地的距离计算(转)

    转自:http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation- ...

随机推荐

  1. SDN学习之Mininet验证OpenFlow协议版本

    最近学习如何使用mininet,但是,刚刚开始时一直无法知道如何查看OpenFlow协议的版本,通过查阅网上的资料,从SDNLAB中,学习到了如何验证,mininet自身基于OpenFlow13版本的 ...

  2. 【Android Widget】1.TextView

    1.创建可被点击的TextView 1.1 在xml中创建可被点击的TextView android:autoLink 是否将符合指定格式的文本转换成可单击的超链接. 属性值可以是如下几个属性值的一个 ...

  3. 堆和栈(java内存)

    栈内存: 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为 ...

  4. The authenticity of host '172.16.33.53 (172.16.33.53)' can't be established的问题(日志六)

    用ssh登录一个机器(换过ip地址)会出现如下错误 weiguohui@weiguohui1-virtual-machine:~/.ssh$ ssh 172.16.33.53The authentic ...

  5. 在QT中创建文件

    最近在做QT东西时遇到在指定路径下创建文件,发现qt中没有直接用的. 主要通过自定义一个createFile()函数来实现,其中需要用到<QFile> <QDir> <Q ...

  6. Java实现八种排序算法(代码详细解释)

    经过一个多星期的学习.收集.整理,又对数据结构的八大排序算法进行了一个回顾,在测试过程中也遇到了很多问题,解决了很多问题.代码全都是经过小弟运行的,如果有问题,希望能给小弟提出来,共同进步. 参考:数 ...

  7. [笔记]机器学习(Machine Learning) - 02.逻辑回归(Logistic Regression)

    逻辑回归算法是分类算法,虽然这个算法的名字中出现了"回归",但逻辑回归算法实际上是一种分类算法,我们将它作为分类算法使用.. 分类问题:对于每个样本,判断它属于N个类中的那个类或哪 ...

  8. OpenStack修复影响宿主机的QEMU漏洞CVE-2017-2615

    距离这个虚拟化层面的漏洞公告发出已有两个多月了,漏洞详情可以查看: 360安全应急响应中心-360发现QEMU严重漏洞 影响国内大部分公有云 简单来说是通过Cirrus VGA操作读取宿主机内存中的内 ...

  9. URI结构

    [scheme:][//host:port][path][?query][#fragment] path:从端口后第一个/开始,可以有多个,每个用/连接. query:从第一个?开始,至行尾或#结束. ...

  10. Python正则表达式完全指南(上)

    正则表达式处理文本有如疾风扫秋叶,绝大部分编程语言都内置支持正则表达式,它应用在诸如表单验证.文本提取.替换等场景.爬虫系统更是离不开正则表达式,用好正则表达式往往能收到事半功倍的效果. 介绍正则表达 ...