热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PostGIS中geometry与geography的区别

作者:WuMY摘要:除了geometry,PostGIS还定义了geography,用于不同的场景需求。以下通过实战对比介绍

作者:WuMY

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

geography基础介绍

与geometry不同的是,geography原生支持地理坐标(也称为大地坐标或经纬度坐标),基于球面模型进行函数分析和计算。下图为两个坐标系:
在这里插入图片描述

geometry与geography对比

以下列举了二者在各个维度间的对比:

对比项geometrygeography
名称几何对象地理对象
坐标系支持平面坐标系和球面坐标系仅支持球面坐标系
对象类型支持 POINT、MULTIPOINT、LINESTRING、LINEARRING、MULTILINESTRING、POLYGON、MULTIPOLYGON、POLYHEDRALSURFACE、TRIANGLE、TIN、GEOMETRYCOLLECTION等简单对象,还支持CIRCULARSTRING、COMPOUNDCURVE、CURVEPOLYGON、MULTICURVE、MULTISURFACE仅支持POINT、LINESTRING、POLYGON、MULTIPOINT、MULTILINESTRING、MULTIPOLYGON、GEOMETRYCOLLECTION
函数限制类型较丰富支持类型较少,仅支持类型转换、长度面积距离计算、交并差运算函数
索引局限性几何索引不能正确处理极地地区查询地理索引可以正确处理覆盖极点或国际日期变更线的查询
元数据geometry_columns:提供了数据库中所有空间数据表的描述信息,分别是数据库名、模式名、空间数据表名,属性列名称,几何图形维度,空间参考标识符,几何图形类型无定义的元数据,需自定义

根据geometry与geography的特点,在使用时可根据以下情况选择:

geometrygeography
如果数据在地理范围上是紧凑的(包含在州、县或市内),推荐使用基于笛卡尔坐标的geometry类型如果需要测量在地理范围上是分散的数据集(覆盖世界大部分地区)距离,推荐使用geography类型。
当做数据存储时,推荐使用geometry由于地理坐标较为精确,因此在进行距离、面积等量算时,建议使用geography
如果用户较为了解投影信息知识,推荐使用geometrygeography不需要了解专业的投影知识只需要知道经纬度就可以进行计算,因此使用门槛较低
当场景需要运用大量复杂函数时,推荐使用geometrygeography的支持函数较少,且计算复杂,因此应用时需要占用较多计算资源。

geometry与geography应用实践

首先我们分别使用geometry和geography类型通过ST_Distance计算北京到昆明之间的距离,空间参考设置为SRID=4326

--geometry对象计算距离
SELECT ST_Distance('SRID=4326;POINT(116.415767 39.916042)'::geometry, -- Beijing'SRID=4326;POINT(102.833963 24.916456)'::geometry -- Kunming);
--结果
20.234944528360142

可以看到,采用geometry在平面坐标系上计算的结果并不正确

--转成geography对象计算距离SELECT ST_Distance('SRID=4326;POINT(116.415767 39.916042)'::geography, -- Beijing'SRID=4326;POINT(102.833963 24.916456)'::geography -- Kunming);--结果
2091929.28729987

计算结果是2092千米,采用geography对象在球面坐标系计算的结果正确,两点的距离量算为大圆航线的一部分。但是该函数只适用于点对象。那我们可以尝试接入构造函数解决这一问题:

-- ST_GeographyFromText(text)
SELECT ST_Distance(ST_GeographyFromText('POINT(116.415767 39.916042)'), -- BeijingST_GeographyFromText('POINT(102.833963 24.916456)') -- Kunming
);
--结果
2091929.28729987

可以看到,使用 ST_GeographyFromText(text) 函数计算,也得到了正确的结论。因此在加入其它几何对象的计算需求下,可使用这种方法进行计算,如计算北京到昆明航线离上海的最短距离时,可采用以下做法:

--北京到昆明航线离上海的最短距离,即垂线段距离:
SELECT ST_Distance(ST_GeographyFromText('LINESTRING(116.415767 39.916042, 102.833963 24.916456)'), -- Beijing to KunmingST_GeographyFromText('POINT(121.452027 31.242725)') -- Shanghai
);
--结果
988436.03069308

得到正确的结果为988千米

geometry与geography互转

为了方便进行准确运算并且可以灵活运用丰富的函数类型,PostGIS提供了二者之间的互转,满足多场景应用。

  • geometry转为geography

为了将geometry数据加载到geography表中,首先需要将geometry转换到EPSG:4326(经度/纬度),然后再将其转换为geography。 ST_Transform(geometry, srid) 函数能将坐标转换为地理坐标,Geography(geometry) 函数能将基于EPSG:4326的geometry数据类型转换为geography数据类型,流程如下:
在这里插入图片描述

--使用ST_Transform(geometry, srid)和Geography(geometry)两个嵌套函数将nyc_subway_stations示例数据从geom转换为geog
CREATE TABLE nyc_subway_stations_geog AS
SELECTGeography(ST_Transform(geom,4326)) AS geog,name,routes
FROM nyc_subway_stations;

同时,当数据量大时,支持创建空间索引,在geography表上构建空间索引与在geometry表上构建空间索引的方法完全相同:

--创建GiST索引类型
CREATE INDEX nyc_subway_stations_geog_gix
ON nyc_subway_stations_geog USING GIST (geog);

  • geography转为geometry

虽然geography类型的空间函数可以解决许多问题,但有时仍需要使用geometry类型支持的其他空间函数,需要将对象从geography转换为geometry。以下city表为例:

--GEOGRAPHY的列名为geog
CREATE TABLE city (code VARCHAR(3),geog GEOGRAPHY(Point));INSERT INTO cityVALUES ('BJ', 'POINT(116.41 39.916042)');
INSERT INTO cityVALUES ('KM', 'POINT(102.833963 24.956)');
INSERT INTO cityVALUES ('SH', 'POINT(121.452 31.245)');

利用SQL语句查询geography元数据,可以看到geography给city表的geog列指定了默认的srid=4326:

SELECT * FROM geography_columns;

结果如下:
在这里插入图片描述

利用类型转换方法,函数将geog转为geometry类型,并调用 ST_X 方法读取转换后的坐标:

SELECT code, ST_X(geog::geometry) AS longitude FROM city;

结果为如下图,可以看到采用类型转换的方法,并不会改变geometry本身的坐标值。

在这里插入图片描述

总结:

以上通过各类实战系统对比了geometry与geography从本质上的差别、二者的适用场景及相互转换的方法。更多信息可参考Yukon在线帮助 。


推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
author-avatar
妖童J
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有