postgresql 计算距离

2020-05-13  本文已影响0人  EdgeE

原文链接:https://blog.csdn.net/weixin_36343850/article/details/87977317

背景:PostgreSQL 可以扩展PostGIS 模块,来完成地理空间计算方面的任务
问题描述:使用内置函数 ST_Length来计算轨迹长度时,发现计算的结果和实际不太符合,查阅相关博客发现原来是坐标系的问题。(但是各个博客的内容可能不太准确,折腾了半天,最后找到官网,成功把问题解决,只能说,官网是个好东西)
问题解决:
概念: geometry和geography的区别

先来看看官网的描述(点击蓝色的两个字可以直达官网):

ST_Length — Returns the 2D length of the geometry if it is a LineString or MultiLineString. geometry are in units of spatial reference and geography are in meters (default spheroid)

输入LineString 或者 MultiLineString 格式的数据,然后返回二维的长度。对于geometry类型,返回对应空间参考系的单位,对于geography返回以米为单位。

再看看函数定义
float ST_Length(geometry a_2dlinestring);
float ST_Length(geography geog, boolean use_spheroid=true);

很明显,是分为两种输入类型来的。两种不同的输入返回输入的结果。而对于geography 类型的use_spheroid这个参数,默认为true,用来指定是否使用参考面(因为地图是个不规则球体,有各种参考面),如果为false,则不使用参考面,把地球当做一个完美的球体来看待,因而精度会降低,但是能剩下不少计算的时间。

具体解决办法
回归到问题, 直接把LineString 或 MultiLineString输入函数,属于 geometry 类型,所以如果是计算地理上面的数据,是不准确的。因此,使用ST_GeographyFromText函数将数据从geometry 类型转换为geography ,然后再进行计算,调用的就是第二个方法,得到正确的结果。
官网示例:

SELECT ST_Length(the_geog) As length_spheroid,  
ST_Length(the_geog,false) As length_sphere
FROM  (
SELECT ST_GeographyFromText('SRID=4326;LINESTRING(-72.1260 42.45, -72.1240 42.45666, -72.123 42.1546)') As the_geog ) As foo;

结果:

length_spheroid | length_sphere
------------------±-----------------
34310.5703627288 | 34346.2060960742

个人示例:

查看原始数据

SELECT gid,geom FROM bfmap_ways limit 10;

从上图可以看到,原始数据有两个字段,gid和geom,其中geom是二进制格式。

使用st_astext将二进制格式转换为文本格式,然后使用ST_GeographyFromText将数据转换为Geography格式,最后用st_length计算长度

SELECT gid, st_astext(geom) as geom,
st_length(ST_GeographyFromText(st_astext(geom))) as length 
FROM bfmap_ways limit 10;

总结:不清楚的时候,尽可能去找官网!官网的描述最准确,最详细!最后再一次附上官网 http://postgis.net/docs/manual-2.3/ST_Length.html

上一篇 下一篇

猜你喜欢

热点阅读