美文网首页
postgresql 计算距离

postgresql 计算距离

作者: EdgeE | 来源:发表于2020-05-13 11:59 被阅读0次

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

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

    • geometry:planar 平面坐标系【supported by SQL Server conforms to the Open Geospatial Consortium (OGC) Simple Features for SQL Specification version 1.1.0.】
    • geography: terrestrial 地理坐标系【stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.】
      也就是说,geometry是一个平面几何的概念,而geography是一个地球的地理的概念。所以当两个点形成一条轨迹时,输入经纬度直接采用geometry即几何的方法来算的话,会不准,因为地球是一个球体,而不是一个简单的平面。
      ST_Length函数的使用

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

    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

    相关文章

      网友评论

          本文标题:postgresql 计算距离

          本文链接:https://www.haomeiwen.com/subject/knqnnhtx.html