[toc]
简介
PostGIS是 postgresql 的一个扩展插件,PostGIS 通过添加对存储、索引和查询地理空间数据的支持,扩展了 PostgreSQL 关系数据库的功能,让其在处理地理空间数据的时候更加高效。
PostGIS 功能包括:
- 空间数据存储:在 2D 和 3D 数据中存储不同类型的空间数据,例如点、线、多边形和多几何图形。
- 空间索引:根据空间数据的位置快速搜索和检索空间数据。
- 空间函数:广泛的空间函数,允许您筛选和分析空间数据、测量距离和面积、相交几何图形、缓冲等。
- 几何图形处理:用于处理和操作几何图形数据的工具,例如简化、转换和泛化。
- 栅格数据支持:栅格数据的存储和处理,例如高程数据和天气数据。
- 地理编码和反向地理编码:用于地理编码和反向地理编码的函数。
- 集成:使用第三方工具(如 QGIS、GeoServer、MapServer、ArcGIS、Tableau)访问和使用 PostGIS。
安装
在DbServer上安装PostGIS
前提是已经安装好了 postgresql ,而后在dbServer 上面执行如下脚本安装 PostGIS扩展:
#nstall EPEL repo RPM: dnf -y install epel-release
#Enable PowerTools repo (required for some of the dependencies): dnf -y config-manager --set-enabled PowerTools
# you might need to do this instead for the Rockys dnf config-manager --enable crb
# for Rocky 8 and above might need to do this as well crb enable
# Now, you can finally install PostGIS
# Select the right PostGIS and PostgreSQL versions dnf -y install postgis34_16 systemctl restart postgresql-16
启用
在 PostgreSQL 中,扩展(如 PostGIS)是按数据库(即schame)安装的,而不是全局安装的。也就是说,PostGIS 可能在一个数据库中已经安装,但在另一个数据库中并不一定可用。
每个数据库都需要单独安装和启用 PostGIS 扩展。比如在 postgres 库(或者说schame更贴切)中安装了PostGIS,但是在ramble库(即schame)中是不可用的,需要在ramble中执行如下命令启用:
-- 安装postgis扩展
CREATE EXTENSION postgis;
-- 查看版本
SELECT PostGIS_Version();
-- 查看完整版本
SELECT postgis_full_version();
-- 查询当前 schame 所有扩展
SELECT * FROM pg_extension;
数据类型
geometry
geometry 是 PostGIS 中最通用的空间数据类型,用于存储几何对象,例如点、线、面等。它支持不同的几何类型,并且可以指定坐标参考系统(SRID)。
常见几何类型:
- Point:表示一个单一的坐标点。
- LineString:表示一条由多个点构成的折线。
- Polygon:表示一个多边形,通常由一组线段组成,且需要定义一个闭合区域。
- MultiPoint:表示一组点。
- MultiLineString:表示一组线段。
- MultiPolygon:表示一组多边形。
- GeometryCollection:表示一个几何对象的集合,可以包含不同类型的几何对象。
示例:
CREATE TABLE spatial_data (
id SERIAL PRIMARY KEY,
geom geometry(Point, 4326)
);
geography
geography 类型用于存储地理坐标(即地球表面上的坐标),考虑到了地球的曲率,适合存储大范围的空间数据。与 geometry 类型不同,geography 类型计算空间距离时使用地球的真实形状(球面距离)。
常见几何类型:
- Point
- LineString
- Polygon
- MultiPoint
- MultiLineString
- MultiPolygon
示例:
CREATE TABLE spatial_data (
id SERIAL PRIMARY KEY,
geom geography(Point, 4326)
);
- 4326:表示使用84坐标系
raster
raster 类型用于存储栅格数据(如卫星图像、气候数据、数字高程模型等)。栅格数据由像素组成,每个像素有一个值,可以表示不同的属性(如温度、湿度或高程)。raster 类型支持各种操作,如空间分析、像素查询等。
示例:
CREATE TABLE raster_data (
id SERIAL PRIMARY KEY,
rast raster
);
box2d 和 box3d
- box2d:用于表示二维矩形区域,由两个点(对角线的两个端点)定义。
- box3d:用于表示三维矩形区域,定义方式类似于 box2d,但增加了 z 坐标。
示例:
CREATE TABLE bounding_boxes (
id SERIAL PRIMARY KEY,
bbox box2d
);
path
path 类型用于表示一条路径,它可以是开放的或闭合的。路径由一系列点连接而成。路径可以是一个封闭的多边形或不封闭的线。
circle
circle 类型用于表示一个圆形区域,由圆心的坐标和半径定义。与其他几何类型不同,circle 类型只包含圆的属性,而不关心具体的形状。
geometry 和 geography 使用场景
geography 类型对于数据具有全球范围的用户以及不想了解投影坐标系的用户来说非常方便。但是,对旋转椭球体的计算成本非常高,因此许多查询在 geography 中比在 geometry 中慢。
geometry 类型易于理解,表示笛卡尔平面上的数据。PostGIS 中的所有向量函数都与几何函数对应。如果数据还没有平面“空间参考系”,则必须为数据选择一个平面“空间参考系”,即坐标系。这样所有计算都将非常简单,并且运行速度比geography 快得多。
总结,如果可以将数据整合到平面坐标系中(如果它的范围不是真正的全局坐标系,即全球),则应考虑使用 geometry 而不是 geography。
例如:开发一个用户覆盖全球的app,那么推荐使用 geography ,如果用户仅针对某一个国家,推荐 geometry。
构造几何对象
构造 POINT
select ST_SetSRID( ST_MakePoint(117.123376,39.17076) , 4326)
构造 LINESTRING
SELECT ST_GeomFromText('LINESTRING (117.123376 39.17076,117.125000 39.172000)',
4326) AS linestring;
构造 MultiPolygon
select st_setsrid(st_geomfromgeojson('{
"type": "MultiPolygon",
"coordinates": [
[
[
[
117.123376,
39.17076
],
[
117.121552,
39.163932
],
[
117.080016,
39.173138
],
[
117.096324,
39.175148
],
[
117.123376,
39.17076
]
]
]
]
}'),4326)
SRID相关
查询某字段的SRID
SELECT ST_SRID(way) FROM planet_osm_line;
转换字段的SRID
SELECT ST_Transform (way,4326) FROM planet_osm_line;
计算面是否包含点的函数
ST_Within
ST_Within(A, B) 返回 TRUE 如果几何对象 A 完全位于几何对象 B 内部,即 A 是 B 的子集。A 必须完全在 B 内部,A 不能与 B 的边界重合,不能超出 B 的边界。
判断一个区域是否完全在另一个区域内。
SELECT ST_Within(geometry 'POINT(1 1)', geometry 'POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))');
-- 返回 TRUE,因为点 (1,1) 完全在多边形内
ST_Contains
ST_Contains(A, B) 返回 TRUE 如果几何对象 A 完全包含几何对象 B,即 B 必须完全位于 A 内部。A 必须完全包含 B,B 不能与 A 的边界重合,不能超出 A 的边界。
判断一个区域是否包含另一个区域。
SELECT ST_Contains(geometry 'POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))', geometry 'POINT(1 1)');
-- 返回 TRUE,因为多边形完全包含点 (1,1)
ST_Covers
ST_Covers(A, B) 返回 TRUE 如果几何对象 A 覆盖了几何对象 B,即 B 的所有部分都被 A 覆盖,但不要求 A 必须完全包含 B。允许 A 和 B 的边界重合。
A 可以包含 B 的所有部分(包括边界),但是不一定要求 A 完全包含 B,而且 A 和 B 可以共享边界。
用于判断一个区域是否覆盖了另一个区域,允许两者有共同的边界。
SELECT ST_Covers(geometry 'POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))', geometry 'POLYGON((1 1, 1 3, 3 3, 3 1, 1 1))');
-- 返回 TRUE,因为多边形 A(POLYGON((0 0, 0 2, 2 2, 2 0, 0 0)))覆盖了多边形 B(POLYGON((1 1, 1 3, 3 3, 3 1, 1 1))),即 B 被完全覆盖。
常用函数
函数名 | 说明 | 示例 |
---|---|---|
ST_IsClosed | 计算围栏是否闭合 | ST_Contains 和 ST_Covers 都要求多边形是闭合的 |
ST_Distance | 计算距离 | |
ST_AsText | 将geom 转成字符串 | ST_AsText(geom) ,转换后:POLYGON((116 39,116 40,117 40,117 39,116 39)) |
ST_Transform | 转换为其它坐标系 | ST_Transform(geom, 4326) |
ST_MakePoint | 构造一个点 | ST_MakePoint(116,40) |
ST_SetSRID | 设置 srid | ST_SetSRID( ST_MakePoint(116,40) , 4326) |
ST_Centroid | 求中心点,适用与规则的范围,特殊的范围如“C”字型的则不适用 | |
ST_PointOnSurface | 求中心点,得到的点一定在范围内,即使范围是一个“C”字型的 | |
ST_Buffer | 获取缓冲区,例如对一个岛屿周边10公里实行海域管制 | |
ST_Intersection | 求交集, 返回两个参数共有的空间区域(或线或点)。如果参数不相交,则函数返回空几何图形 | ST_Intersection(geometry A, geometry B |
ST_Union | 求并集 | |
ST_Area | 求面积 | |
ST_GeometryType | 返回几何图形的类型 | |
ST_NumGeometries | 返回集合中的几何图形数,或者 1 返回简单几何图形 | |
ST_GeomFromGeoJSON | 从 GeoJSON 数据构造一个 MultiPolygon | SELECT ST_GeomFromGeoJSON('{ "type": "MultiPolygon", "coordinates": [ [ [[0, 0], [0, 5], [5, 5], [5, 0], [0, 0]] ], [ [[6, 0], [6, 5], [10, 5], [10, 0], [6, 0]] ] ]}') AS multipolygon; |
常用sql
扩展相关
SELECT * FROM pg_extension;
SELECT postgis_full_version();
-- 在当前 schema 中启用 postgis 扩展
create extension postgis ;