平面坐标,球面坐标

SRID=2369  投影坐标
SRID=4326  球面坐标
ST_Transform(ST_GeomFromText('POINT(120.08 30.96)', 4326), 2390 )  坐标系转换函数

PostGIS中有两种常用的空间类型geometry和geography,这两种数据类型有什么差异,应该如何选择?

对于GIS来说,首先是坐标系,有两种:一种是球坐标(地理坐标),另一种是平面坐标(投影坐标)。

球坐标通常用于计算,平面坐标通常用于展示(也可以计算)。

投影坐标是从球坐标投影后展开得来(用一个圆柱将地球包起来,把地球当成会发光的光源,投影后,将圆柱展开得到),投影的范围越大,精度就越低。范围越小,精度就越高。除了投影扇形的大小有区别,在不同的行业,也有不同的坐标系,例如用于测绘的坐标系。

目前用得最多的有SRID=4326球坐标,SRID为EPSG:3785的墨卡托投影坐标。

再来说geometry和geography两种类型,geometry支持平面对象也支持空间对象,而geography则仅支持空间对象。

geometry支持更多的函数,一些几何计算的代价更低。

geography支持的函数略少,计算代价更高。那为什么还要geography呢?因

  1. 4.2.2. When to use Geography Data type over Geometry data type

  2. The geography type allows you to store data in longitude/latitude coordinates,

  3. but at a cost: there are fewer functions defined on GEOGRAPHY than there are on GEOMETRY;

  4. those functions that are defined take more CPU time to execute.

  5. The type you choose should be conditioned on the expected working area of the application you are building.

  6. Will your data span the globe or a large continental area, or is it local to a state, county or municipality?

  7. If your data is contained in a small area, you might find that choosing an appropriate

  8. projection and using GEOMETRY is the best solution, in terms of performance and functionality available.

  9. If your data is global or covers a continental region, you may find that GEOGRAPHY

  10. allows you to build a system without having to worry about projection details.

  11. You store your data in longitude/latitude, and use the functions that have been defined on GEOGRAPHY.

  12. If you don't understand projections, and you don't want to learn about them,

  13. and you're prepared to accept the limitations in functionality available in GEOGRAPHY,

  14. then it might be easier for you to use GEOGRAPHY than GEOMETRY.

  15. Simply load your data up as longitude/latitude and go from there.

  16. Refer to Section 14.11, “PostGIS Function Support Matrix” for compare between

  17. what is supported for Geography vs. Geometry.

  18. For a brief listing and description of Geography functions,

  19. refer to Section 14.4, “PostGIS Geography Support Functions”

既然提到距离计算和投影坐标系有关,引入了本文的问题:

在不知道要计算的geometry点,在什么投影坐标系下时,往往计算距离得到的结果并不准确。

例如,下面的点,换算成2163坐标系,计算距离得到的结果并不准确。

  1. db1=# SELECT st_distance(ST_Transform(ST_GeomFromText('POINT(120.08 30.96)', 4326), 2163 ), ST_Transform(ST_GeomFromText('POINT(120.08 30.92)', 4326), 2163 ));

  2. st_distance

  3. ------------------

  4. 4030.46766234184

  5. (1 row)

2163坐标系内容如下:

  1. postgres=# select * from spatial_ref_sys where srid=2163;

  2. -[ RECORD 1 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  3. srid | 2163

  4. auth_name | EPSG

  5. auth_srid | 2163

  6. srtext | PROJCS["US National Atlas Equal Area",GEOGCS["Unspecified datum based upon the Clarke 1866 Authalic Sphere",DATUM["Not_specified_based_on_Clarke_1866_Authalic_Sphere",SPHEROID["Clarke 1866 Authalic Sphere",6370997,0,AUTHORITY["EPSG","7052"]],AUTHORITY["EPSG","6052"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4052"]],PROJECTION["Lambert_Azimuthal_Equal_Area"],PARAMETER["latitude_of_center",45],PARAMETER["longitude_of_center",-100],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],AUTHORITY["EPSG","2163"]]

  7. proj4text | +proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs

  1. AUTHORITY["EPSG", "9122"]指的是EPSG数据集中UNIT为degree的ID是9122;

  2. AUTHORITY["EPSG", "4326"]指的是地理坐标系WGS 84的ID是4326;

  3. AUTHORITY["EPSG", "9001"]指的是EPSG中UNIT为meter的ID是9001;

  4. AUTHORITY["EPSG", "32650"]指的是该投影坐标系WGS 84 / UTM zone 50N的ID是32650

这样会造成一个假象如下:

  1. 用st_distance函数计算出来的经纬度之间的距离,跟用java程序算出来的距离相差很大。

  2. 这个例子,st_distance算出来的距离是4030,我们程序算出来的是4445,换另外两个相距很远的点,这个差距值会更大。

正确姿势

算球面距离,不要算直线距离。

1、使用球坐标,通过st_distancespheroid计算两个geometry类型的球面距离。

对于geometry类型,可以使用st_distancespheroid直接用球坐标计算,在计算时会自动设置这个椭球特性(SPHEROID["Krasovsky_1940",6378245.000000,298.299997264589] )。

  1. postgres=# SELECT st_distancespheroid(ST_GeomFromText('POINT(120.08 30.96)', 4326),ST_GeomFromText('POINT(120.08 30.92)', 4326), 'SPHEROID["WGS84",6378137,298.257223563]');

  2. st_distancespheroid

  3. ---------------------

  4. 4434.73734584354

  5. (1 row)

2、使用平面坐标,通过st_distance计算两个geometry类型的平面投影后的距离。

采用精准的投影坐标(小面积投影坐标系)(但是必须要覆盖到要计算的两个点)

ST_Transform(ST_GeomFromText('POINT(120.08 30.96)', 4326), 2163 )

如果geometry值的SRID不是(高精度)目标坐标系,可以使用ST_Transform函数进行转换,转换为目标投影坐标系,再计算距离。

  1. postgres=# SELECT st_distance(ST_Transform(ST_GeomFromText('POINT(120.08 30.96)', 4326), 2390 ), ST_Transform(ST_GeomFromText('POINT(120.08 30.92)', 4326), 2390 ));

  2. st_distance

  3. ------------------

  4. 4547.55477647394

  5. (1 row)

3、使用球坐标,通过ST_Distance计算两个geography类型的球面距离。

  1. float ST_Distance(geography gg1, geography gg2, boolean use_spheroid); -- 适用椭球体(WGS84)

  2. use_spheroid设置为ture表示使用:

  3. -- WGS84 椭球体参数定义

  4. vspheroid := 'SPHEROID["WGS84",6378137,298.257223563]' ;

这里的XXXX就是你要选择的球坐标系SRID。在spatial_ref_sys表里可以查看各种坐标系。

  1. postgres=# SELECT st_distance(ST_GeogFromText('SRID=xxxx;POINT(120.08 30.96)'), ST_GeogFromText('SRID=xxxx;POINT(120.08 30.92)'), true);

  2. st_distance

  3. ----------------

  4. xxxxxxxxxxxxxxxxxxxx

  5. (1 row)

  6. 例如

  7. postgres=# SELECT st_distance(ST_GeogFromText('SRID=4610;POINT(120.08 30.96)'), ST_GeogFromText('SRID=4610;POINT(120.08 30.92)'), true);

  8. st_distance

  9. ----------------

  10. 4434.739418211

  11. (1 row)

如果允许一定的偏差,可以使用全球球坐标系4326。

  1. postgres=# SELECT st_distance(ST_GeogFromText('SRID=4326;POINT(120.08 30.96)'), ST_GeogFromText('SRID=4326;POINT(120.08 30.92)'), true);

  2. st_distance

  3. ----------------

  4. 4434.737345844

  5. (1 row)

geography只支持球坐标系,使用投影坐标会报错。

  1. postgres=# SELECT st_distance(ST_GeogFromText('SRID=2369;POINT(120.08 30.96)'), ST_GeogFromText('SRID=2369;POINT(120.08 30.92)'), true);

  2. 错误: 22023: Only lon/lat coordinate systems are supported in geography.

  3. LOCATION: srid_is_latlong, lwgeom_transform.c:774

4、指定SPHEROID内容,通过st_distancesphereoid计算geometry的球面距离。

这种方法最为精确,但是要求了解计算距离当地的地形属性(即输入参数的spheroid的内容)。

  1. db1=# SELECT st_distancespheroid(ST_GeomFromText('POINT(120.08 30.96)', 4326),ST_GeomFromText('POINT(120.08 30.92)', 4326), 'SPHEROID["WGS84",6378137,298.257223563]');

  2. st_distancesphere

  3. -------------------

  4. 4447.803189385

  5. (1 row)

小结

计算距离,应该考虑到被计算的两点所在处的地球特性(spheroid)。这样计算得到的距离才是最精确的。

geometry和geography类型的选择,建议使用geometry,既能支持球坐标系,又能支持平面坐标系。主要考虑到用户是否了解位置所在处的地理特性,选择合适的坐标系。

  1. -- 适用平面直角坐标,适用geometry类型,计算直线距离

  2. float ST_Distance(geometry g1, geometry g2);

  3. -- 适用椭球体坐标,适用geography类型,计算球面距离

  4. float ST_Distance(geography gg1, geography gg2);

  5. -- 适用椭球体坐标(WGS84),适用geography类型,计算球面距离

  6. float ST_Distance(geography gg1, geography gg2, boolean use_spheroid);

  7. use_spheroid设置为ture表示使用:

  8. vspheroid := 'SPHEROID["WGS84",6378137,298.257223563]' ; -- WGS84 椭球体参数定义

  9. -- 适用椭球体坐标以及投影坐标,适用geometry类型,求球面距离(需要输入spheroid)

  10. float ST_DistanceSpheroid(geometry geomlonlatA, geometry geomlonlatB, spheroid measurement_spheroid);

参考

1、计算球面距离

http://postgis.net/docs/manual-2.4/ST_DistanceSphere.html

2、计算球面以及平面距离(取决于输入的类型geometry还是geography)

http://postgis.net/docs/manual-2.4/ST_Distance.html

3、坐标系转换

http://postgis.net/docs/manual-2.4/ST_Transform.html

4、投影坐标和球坐标

《地理坐标系(球面坐标系)和投影坐标系(平面坐标系)》

5、PostGIS学习建议

《PostGIS 空间数据学习建议》

6、http://blog.163.com/jey_df/blog/static/18255016120149145755781/

https://desktop.arcgis.com/zh-cn/arcmap/10.3/guide-books/map-projections/mercator.htm

PostGIS 距离计算规范 - 投影 与 球 坐标系, geometry 与 geography 类型相关推荐

  1. PostGIS中geometry与geography的区别

    作者:WuMY 摘要:除了geometry,PostGIS还定义了geography,用于不同的场景需求.以下通过实战对比介绍geometry与geography之间的差异.适用场景及互转方法. ge ...

  2. 屏幕距离和坐便转换工具_投影幕尺寸计算、投影距离计算、观影距离计算

    随着生活水平的提高,现在私人家庭影院已经开始慢慢进入寻常人家庭,私人影院已经不是土豪的专利.私人影院不一定需要独立专用的房间,在客厅也可以大屏幕看电影,近几年很火的激光电视,主打的就是客厅大屏显示市场 ...

  3. html5 canvas获取坐标系,HTML5 Canvas球坐标系投影到二维直角坐标系实例演示

    JavaScript 语言: JaveScriptBabelCoffeeScript 确定 function g(e) { return document.getElementById(e); } v ...

  4. python计算球坐标系的积分_Python实现将n个点均匀地分布在球面上的方法

    将10000左右个点均匀地分布在一个球面上.所谓的均匀,即相邻的两个点之间的距离尽量一致. 算法是用基于正多面体剖分球面,选的是正八面体. #!/usr/bin/python # -*- coding ...

  5. 坐标计算距离公式 火星坐标系_WGS84、GCJ02、BD09地图坐标系间的坐标转换及坐标距离计算...

    坐标转换转载来源:http://nightfarmer.github.io/2016/12/01/GPSUtil/ 坐标系 解释 使用地图 WGS84 地球坐标系,国际上通用的坐标系.设备一般包含GP ...

  6. 三重积分--------球坐标系

    最近在复习高数,三重积分一直无法很好的理解.直到看到这篇博文感觉茅塞顿开,可能是自己想通了,也可能是博文写的好.只因此文对我帮助甚大,特此转写,希望也能给别人提供帮助. 如果作者,觉得有何不妥,可联系 ...

  7. 双球坐标系_坐标系为啥有多种,笛卡尔坐标系、柱坐标系、球坐标系都有啥区别...

    什么是坐标系 坐标系,是理科常用辅助方法.为了说明质点的位置.运动的快慢.方向等,必须选取其坐标系.在 参照系 中,为确定空间一点的位置,按规定方法选取的有次序的一组数据,这就叫做"坐标&q ...

  8. [转]地理投影,常用坐标系详解、WGS84、WGS84 Web墨卡托、WGS84 UTM、北京54坐标系、西安80坐标系、CGCS2000坐标系...

    转自:http://www.rivermap.cn/docs/show-1829.html 常用坐标系详解 (一)WGS84坐标系 WGS-84坐标系(World Geodetic System一19 ...

  9. Java 通过已知点的经纬度,相对角度,距离计算另一点的经纬度

    问题背景:自己在使用高德地图时没有发现通过已知点经纬度,角度,距离计算另一点经纬度的方法,所以只好自己实现了.查询之后发现国内的博客基本都是计算两点距离,计算点到线距离的距离等,有几篇也都是C语言形式 ...

最新文章

  1. Paper8:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
  2. js实现的简单模态对话框
  3. ubuntu系统虚拟机linux系统,基于虚拟机的Linux操作系统安装(Ubuntu
  4. YOLOv5在建筑工地中安全帽佩戴检测的应用(已开源+数据集)
  5. asp.net怎样在URL中使用中文、空格、特殊字符
  6. bzoj 1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(暴力)
  7. paip.java 调用c++ dll so总结
  8. 毕设题目:Matlab飞行器
  9. SNMP 简单网络管理协议
  10. 2020年阴历二月二十九 投资理财~业余投资者如果不深入研究财报该怎么办?
  11. angular路由守卫
  12. 在vscode拉取代码时would clobber existing tag
  13. 网易面试总结——面试案例9~面试案例12
  14. python snmp-cmds get示例
  15. js简单插件(饼形图)
  16. excel计算标准分
  17. 使用Xcode查看当前渲染性能以及渲染情况
  18. 【HTTP】10分钟带你快速了解HTTP中常见的状态码(内附大量实例)
  19. linux环境js打不开,linux 环境无法通过egg-scripts start启动项目,wait start 300超时退出...
  20. FreeBSD 图解安装--转自panabit官网

热门文章

  1. yunfile高级会员帐号获取器V1.0绿色版
  2. 哈密顿量模拟(Hamiltonain simulation)
  3. 咕咕机GT1,能用纸条传达浓浓爱意的迷你打印机
  4. 开发者方案 · 久坐提醒 / 喝水提醒小助手·树莓派4B/咕咕机G2/涂鸦 Link SDK
  5. 网络爬虫:爬取某地区短租房信息
  6. Marvolo Gaunt's Ring ---CodeForces - 855B(思维题)
  7. 鸿蒙之境全关卡,神都夜行录鸿蒙之境攻略
  8. 蓝牙核心技术概述(五):蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)
  9. public,static,private,protected的用法
  10. css实现文字无缝横向滚动