PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询
PostGIS官网:About PostGIS | PostGIS
PostGIS官方教程:PostGIS 简介 — Introduction to PostGIS
PostGIS相关教程:文章目录汇总 - 知乎 (zhihu.com)
本文基于官方教程描述PostGIS中的九交模型
数据准备可参考:
数据介绍可参考:
"维数扩展的9交集模型-Dimensionally Extended 9-Intersection Model"(DE9IM)是一个用于建模两个空间对象如何交互的框架(即,空间关系)
九交模型规定,每个几何图形都有外部、边界和内部:
对于点:内部是点,边界是空集,外部是平面上除点以外的所有其他部分
点线面的外部、边界和内部定义表格如下:
几何对象 | 边界 | 内部 | 外部 |
---|---|---|---|
点 | 无边界 | 点本身 | 点对象以外的区域 |
线 | 线对象的端点 | 除端点外的线对象 | 线对象外的区域 |
面 | 面对象控制边 | 面对象除边界后的区域 | 面对象本身外的区域 |
九交模型进一步规定:
任意对象a、b:
内部(b) | 边界(b) | 外部(b) | |
---|---|---|---|
内部(a) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) |
边界(a) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) |
外部(a) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) | dim(I(a) intersect I(b)) |
示例图如下:
dim(dimension)的返回值:有-1,0,1,2. 分别代表不同的含义,如下:
例如,下图所示的图形:
其九交模型为:
1 0 1
0 F 0
2 1 2
使用PostGIS进行判断,主要使用的函数有:
SELECT ST_Relate(
'LINESTRING(0 0, 2 0)',
'POLYGON((1 -1, 1 1, 3 1, 3 -1, 1 -1))'
);
E9IM矩阵的强大之处在于使用它们作为匹配参数来查找彼此之间具有特定关系的几何图形
比如下图中,利用九交模型寻找合格的码头:
将码头与湖泊建模进数据库:
CREATE TABLE lakes ( id serial primary key, geom geometry );
CREATE TABLE docks ( id serial primary key, good boolean, geom geometry );
INSERT INTO lakes ( geom )
VALUES ( 'POLYGON ((100 200, 140 230, 180 310, 280 310, 390 270, 400 210, 320 140, 215 141, 150 170, 100 200))');
INSERT INTO docks ( geom, good )
VALUES
('LINESTRING (170 290, 205 272)',true),
('LINESTRING (120 215, 176 197)',true),
('LINESTRING (290 260, 340 250)',false),
('LINESTRING (350 300, 400 320)',false),
('LINESTRING (370 230, 420 240)',false),
合格的码头具有以下特点:
用九交模型定义:
使用九交模型寻找合适的码头:
SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1FF00F212');
DE9IM数据模型字符串可以使用通配符:
利用九交模型,来检测几何图形是否合格
例如,任何人口普查块(census blocks)都不应与任何其他人口普查块重叠,如下图所示:
使用九交模型表示内部重叠就是:
2 * *
* * *
* * *
使用这个九交模型来检测:
SELECT a.gid, b.gid
FROM nyc_census_blocks a, nyc_census_blocks b
WHERE ST_Intersects(a.geom, b.geom)
AND ST_Relate(a.geom, b.geom, '2********')
AND a.gid != b.gid;
又例如,使用九交模型检测街道线段是否内部相交(相交点只发生在街道直线的末端,而不是中点),如下图所示:
使用九交模型表示合格线段相交:
* * *
* 0 *
* * *
使用九交模型检测不合格的线段:
SELECT a.gid, b.gid
FROM nyc_streets a, nyc_streets b
WHERE ST_Intersects(a.geom, b.geom)
AND NOT ST_Relate(a.geom, b.geom, '****0****')
AND a.gid != b.gid;
[1]26. Dimensionally Extended 9-Intersection Model — Introduction to PostGIS