Postgis使用
一、安装与配置
先查看目前yum源中有哪些版本可用,并安装合适的版本
yum search postgis
安装Postgresql 10对应的版本PostGIS
yum install -y postgis24_10
二、创建GIS数据库
PostGIS是Postgresql的一个扩展,创建数据库并加载PostGIS扩展:
create database geo;
create extension postgis;
三、几何对象
几何对象输入
PostGIS支持很多几何类型:点、线、多边形、复合几何体等,并提供大量实用的相关函数。对于PostGIS而言,所有几何对象都有一个公共父类Geometry,所以在实际使用中,通常PostGIS的空间数据类型使用统一的Geometry类型,无论是点、折线还是多边形,都可以放入Geometry类型字段中。
PostGIS支持多种空间对象创建方式,大体上可以分为几类:
文本格式(WKT,Well-Known-Text)
二进制格式(WKB,Well-Known-Binary)
GeoJSON等编码
返回几何类型的函数
注:所有PostGIS相关函数都是以st开头
例如创建几何点(1,2),可以通过以下四种方式,得到的结果都一样
SELECT
'Point(1 2)'::GEOMETRY AS wkt,
'0101000000000000000000F03F0000000000000040':: GEOMETRY AS wkb,
st_geomfromgeojson('{"type":"Point","coordinates":[1,2]}') AS geo_json,
ST_Point(1,2) AS func;
几何对象存储
PostGIS的几何类型对Postgresql内建的几何类型使用了不同的存储方式。以点为例,使用内置的Point与ST_Point创建一个点,返回结果如下:
SELECT Point(1,2),ST_Point(1,2)
Postgresql中的Point只是一个包含两个Double的结构体(16字节),但PostGIS的点类型ST_Point则采用了不同的存储方式(21字节),除了两个坐标分量,他还包括了一些额外元数据:例如几何对象的实际类型、参考系的ID等。
如果需要人类可读的格式,则可以用ST_AsText输出WKT
SELECT st_astext(ST_Point(1,2))
几何对象运算
(1)两点间距离(几何距离)
SELECT ST_Point(1,1) <-> ST_Point(2,2)
注:上述方法只能用于几何距离计算,不能用于坐标距离计算。
(2)地理坐标距离计算
地理坐标距离计算需要引入地理坐标系(4326号坐标系,指代WGS84国际标准GPS坐标系),只有当两个点用同一坐标系时才能进行计算。
SELECT st_geomfromtext('POINT(116.321367 39.966956)',4326) :: geography <-> st_geomfromtext('POINT(116.315346 39.997398)',4326) :: geography
计算出A(116.321367,39.966956),B(116.315346,39.997398)两点间的距离为3.4km
ST_GeomFromText(character-string[, srid]) 根据字符串表示构造几何
参数
SELECT st_geomfromtext('POINT(116.321367 39.966956)',4326)
st_length可以计算某条路(折线)的总长度
st_area可以计算出某个闭合区域的面积
四、应用场景
场景一
给出一个中心点,找出该点周围一定距离 范围内所有符合条件的对象。例如,找出以用户为中心,周围1公里内所有的公交站,并按距离远近排序。
假设用户正在A地铁站:(116.321367,39.966956),使用PostGIS计算距离
CREATE TABLE stations(
name TEXT,
position geography,
);
SELECT name,ST_Point(116.321367,39.966956)::geography <-> position::geography AS distance FROM stations
WHERE st_point(116.321367,39.966956)::geography <-> position::geography < 500
ORDER BY st_point(116.321367,39.966956)::geography <-> position::geography;
场景二
电子围栏:用点和距离画圆圈人是一种常见场景,另外一种场景是,判断一个点落在了哪些地理围栏中
例如有车辆和用户的位置坐标,现在希望从坐标得到用户所处的城市(或者区域、商圈等),又比如共享单车的禁停区检测,无人机的禁飞区识别,都是这种场景。
--兴趣区域(AOI,Area of Interest)
CREATE TABLE aoi(
name TEXT,
bound GEOMETRY
)
--检测A地铁站中心点所属的商圈
SELECT name FROM aoi WHERE ST_Contains(bound,ST_Point(116.458855,39.909863));
--或
SELECT name FROM aoi WHERE ST_Within(ST_Point(116.458855,39.909863),bound);
ST_Contains与ST_Within介绍
boolean ST_Contains(geometry A, geometry B);
如果geometry B完全在geometry A里面则返回TRUE
boolean ST_Within(geometry A, geometry B);
如果geometry A完全在geometry B里面则返回TRUE
ST_Contains 和ST_Within是相反的,即 ST_Contains(A,B) = ST_Within(B,A)
.
SELECT st_contains(
st_setsrid(st_geomfromtext('POLYGON ((113.49628347923993 34.82665078796983, 113.6050170152778 34.88282716965251, 113.6427533999493 34.815514563935054, 113.5744551359546 34.77978979669181, 113.49008246199834 34.79650279857806, 113.49628347923993 34.82665078796983))'),4326),
st_setsrid(st_point(113.619469,34.823071), 4326))
SELECT st_within(
st_setsrid(st_point(113.619469,34.823071), 4326),
st_setsrid(st_geomfromtext('POLYGON ((113.49628347923993 34.82665078796983, 113.6050170152778 34.88282716965251, 113.6427533999493 34.815514563935054, 113.5744551359546 34.77978979669181, 113.49008246199834 34.79650279857806, 113.49628347923993 34.82665078796983))'),4326))
--locaation为地理坐标表,digital_railing为电子围栏区域表
select * from locaation c,digital_railing d
where st_within(st_setsrid(st_point(c.lng,c.lat), 4326), d.geometry) and d.name = 'XXX'
参考书籍《Postgresql实战》