PostGIS教程十九:维数扩展的9交集模型
目录
“维度扩展的9交集模型–Dimensionally Extended 9-Intersection Model“(DE9IM)是一个用于建模两个空间对象如何交互的框架。
首先,每个空间对象都具有:
- 内部(interior)
- 边界(boundary)
- 外部(exterior)
内部是以环为边界的那一部分;边界是环本身;外部是边界外的一切。
对于线性要素,内部、边界和外部不太为人所知:
内部是以端点为界限的线的那一部分;边界是线性要素的端点;外部是平面中的所有其他部分。
对于点来说,事件更奇怪:内部是点,边界是空集,外部是平面上除点以外的所有其他部分。
使用这些内部、外部和边界的定义,任何一对空间要素之间的关系都可以用一对要素的内部/边界/外部/之间九个可能的交集的维数来表征。
对于上例中的多边形,内部的交集是二维区域,因此矩阵对应部分用”2“填充。边界仅在零维点处相交,因此矩阵部分用”0“填充。
当两个要素的这三个部分(内部,边界,外部)之间没有交集时,将用”F“填充矩阵中对应的部分。
下面是另一个示例,关于线串的一部分和多边形相交的例子:
关于这个它们的交集的DE9IM矩阵如下:
请注意,以上两个要素的边界实际上根本不相交(线的端点与多边形的内部相交,而不是与多边形的边界相交,反之亦然),因此B/B单元用”F“填充。
虽然从视觉上填写DE9IM矩阵很有趣,但如果计算机能够做到这一点就更好了,这就是ST_Relate函数的作用。
前面的示例可以使用简单的矩形和直线进行简化,其空间关系与上面的多边形和线串的空间关系相同:
我们可以使用SQL生成DE9IM信息:
SELECT ST_Relate(
'LINESTRING(0 0, 2 0)',
'POLYGON((1 -1, 1 1, 3 1, 3 -1, 1 -1))'
);
答案(1010F0212)与我们视觉上计算的结果相同,但以9个字符的字符串形式返回。将结果以三行的形式呈现:
但是,DE9IM矩阵的强大之处不在于生成它们,而在于使用它们作为匹配键来查找彼此之间具有特定关系的几何图形。
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),
('LINESTRING (370 180, 390 160)',false);
假设我们有一个包括湖泊(Lakes)和码头(Docks)的数据模型,进一步假设码头必须位于湖泊内部,并且必须在一端接触到湖泊的边界。我们能在数据库中找到所有符合这一规则的码头吗?
我们的合法码头具有以下特点:
- 它们的内部与湖泊内部有一个线性(一维)相交
- 它们的边界与湖泊内部有一个点(0维)相交
- 它们的边界与湖泊边界也有一个点(0维)相交
- 它们的内部与湖泊外部没有相交(F)
所以它们的DE9IM矩阵看起来像这样:
因此,要找到所有合法的码头,我们需要找到所有与湖泊相交的码头(我们用来作为连接键的潜在候选者的超集),然后找到该集合中具有合法关联模式的所有码头。
SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1FF00F212');
-- Answer: our two good docks
注意,ST_Relate的三参数版本的使用,如果模式匹配,则返回ture;如果模式不匹配,则返回false。对于像这样的完全定义的模式,不需要三参数版本—我们可以只使用字符串相等运算符。
但是,对于更松散的模式搜索,三个参数允许模式字符串中的替换字符:
- “*”表示”此单元格中的任何值都可以接受”
- “T”表示”任何非假值(0、1或2)都可以接受”
例如,我们在示例图形中没有包括的一个可能的码头是与湖泊边界具有二维相交的码头:
INSERT INTO docks ( geom, good )
VALUES ('LINESTRING (140 230, 150 250, 210 230)',true);
如果要将这个新增的码头包含在我们的”合法”停靠集中,则需要更改查询中的关联模式。特别地,码头内部和湖泊边界的相交现在可以可以是1(我们的新情况)或F(我们的原始情况)。因此,我们使用模式中的”*“匹配符覆盖所有情况。
SQL语句如下所示:
SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1*F00F212');
-- Answer: our (now) three good docks
一、数据质量测试
TIGER数据在准备时经过仔细的质量控制,因此我们希望我们的数据符合严格的标准。例如:任何普查块(census blocks)都不应与任何其他普查块重叠。我们能测试一下吗?
当然!
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
LIMIT 10;
-- Answer: 10, there's some funny business
同样,我们预计道路数据都是有尾节点的,也就是说,我们预计相交点只发生在直线的末端,而不是中点。
我们可以通过查找相交的街道(因此,我们有一个连接),但边界之间的交点不是零维的(也就是,线端点之间没有接触)来测试这一点:
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
LIMIT 10;
-- Answer: This happens, so the data is not end-noded.
二、函数列表
转载自:https://blog.csdn.net/qq_35732147/article/details/87709276