原文链接: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
网友评论