目录
一、3-D几何图形
二、3-D函数
三、N-D索引
注意:本节介绍许多PostGIS2.0及更高版本才支持的功能。
到目前为止,我们一直在处理2-D几何图形(二维几何图形),只有X和Y坐标。但是PostGIS支持所有几何图形类型额外的维度,对于每个坐标,另外还能支持用于表示高度信息的"Z"维度以及用于添加额外附加信息的"M"维度(通常为时间、道路英里或距离信息)。
对于3-D和4-D几何图形,额外的维度将作为几何图形中每个顶点的额外坐标添加,并且几何图形类型将得到增强,以指示如何解译额外的维度。添加额外维度会为每个基本几何图形额外添加三种几何图形类型:
对于well-known text(WKT)的表示,高维几何图形由ISO SQL/MM规范提供。附加维度信息仅添加到类型名称后的文本字符串中,额外坐标添加在X/Y信息之后,例如:
在处理3-D和4-D几何图形时,ST_AsText()函数将返回上述表示。
对于well-known binary(WKB)表示,高维几何图形的格式由ISO SQL/MM规范提供。该格式的BNF表可在http://svn.osgeo.org/postgis/trunk/doc/bnf-wkb.txt 查询。
除了标准类型的高维形式外,PostGIS还包括一些在三维空间中有意义的新类型:
由于这两种类型都用于对三维对象建模,因此使用Z变量才是真正有意义的。POLYHEDRALSURFACE Z的一个示例是1单位立方体:
POLYHEDRALSURFACE Z (
((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
)
有许多函数可用于计算三维对象之间的关系:
例如,我们可以使用ST_3DDistance函数计算单位立方体与点之间的距离:
-- This is really the distance between the top corner
-- and the point.
SELECT ST_3DDistance(
'POLYHEDRALSURFACE Z (
((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),
((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),
((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),
((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))
)'::geometry,
'POINT Z (2 2 2)'::geometry
);
-- So here's a shorter form.
SELECT ST_3DDistance(
'POINT Z (1 1 1)'::geometry,
'POINT Z (2 2 2)'::geometry
);
-- Both return 1.73205080756888 == sqrt(3) as expected
一旦有了更高维度的数据,对其进行索引可能是有意义的。但是,在应用多维索引(multi-dimensional index)之前,应该仔细考虑数据在所有维度中的分布情况。
索引仅在允许数据库中WHERE条件查询中大幅减少返回行数时才有用。要使更高维度的索引有用,数据必须分布在该维度的广泛范围中(相对于你正在构造的查询)
你可以为任何维度(甚至混合维度)的数据创建多维索引。例如,要在nyc_streets表上创建多维索引。
CREATE INDEX nyc_streets_gix_nd ON nyc_streets
USING GIST (geom gist_geometry_ops_nd);
gist_geometry_ops_nd参数告诉PostGIS使用N-D索引而不是标准的2-D索引。
构建索引后,可以在查询中使用&&&索引操作符,&&&和&&是相同的语义——边界框相交——区别在于,&&&使用几何图形的所有维度来应用这个语义。维数不匹配的几何图形不会相交。
-- Returns true (both 3-D on the zero plane)
SELECT 'POINT Z (1 1 0)'::geometry &&&
'POLYGON ((0 0 0, 0 2 0, 2 2 0, 2 0 0, 0 0 0))'::geometry;
-- Returns false (one 2-D one 3-D)
SELECT 'POINT Z (1 1 1)'::geometry &&&
'POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))'::geometry;
-- Returns true (the volume around the linestring interacts with the point)
SELECT 'LINESTRING Z(0 0 0, 1 1 1)'::geometry &&&
'POINT(0 1 1)'::geometry;
要使用N-D索引搜索nyc_streets表,只需将&&2-D索引运算符替换为&&&3-D索引运算符。
-- N-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&&
ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)' :: geometry,26918);
-- 2-D index operator
SELECT gid, name
FROM nyc_streets
WHERE geom &&
ST_SetSRID('LINESTRING(586785 4492901,587561 4493037)' :: geometry,26918);
结果应该是一样的。一般来说,N-D索引只比2-D索引执行速度稍慢一些,所以只使用N-D索引,因为N-D查询将提高查询的多维度选择性。