28. 3-D¶
28.1. 3-D 几何图形¶
到目前为止,我们一直在使用只有 X 和 Y 坐标的 2-D 几何图形。但 PostGIS 支持所有几何类型上的附加维度,一个“Z”维度用于添加高度信息,一个“M”维度用于每个坐标的附加维度信息(通常是时间、道路里程或上游距离信息)。
对于 3-D 和 4-D 几何图形,额外的维度作为几何图形中每个顶点的额外坐标添加,并且几何图形类型得到增强以指示如何解释额外的维度。添加额外的维度会导致每个几何图元有三个额外的可能的几何类型
点(一种 2-D 类型)由 PointZ、PointM 和 PointZM 类型连接。
线串(一种 2-D 类型)由 LinestringZ、LinestringM 和 LinestringZM 类型连接。
多边形(一种 2-D 类型)由 PolygonZ、PolygonM 和 PolygonZM 类型连接。
等等。
对于众所周知的文本 (WKT) 表示,更高维几何图形的格式由 ISO SQL/MM 规范给出。额外的维度信息只是在类型名称之后添加到文本字符串中,并且额外的坐标添加到 X/Y 信息之后。例如
POINT ZM (1 2 3 4)
LINESTRING M (1 1 0, 1 2 0, 1 3 1, 2 2 0)
POLYGON Z ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))
当处理 3-D 和 4-D 几何图形时,ST_AsText() 函数将返回上述表示。
对于众所周知的二进制 (WKB) 表示,更高维几何图形的格式由 ISO SQL/MM 规范给出。该格式的 BNF 形式可从 https://git.osgeo.org/gitea/postgis/postgis/src/branch/master/doc/bnf-wkb.txt 获取。
除了标准类型的更高维形式之外,PostGIS 还包含一些在 3-D 空间中很有意义的新类型
TIN 类型允许您将三角形网格建模为数据库中的行。
POLYHEDRALSURFACE 允许您在数据库中对体积对象进行建模。
由于这两种类型都是用于对 3-D 对象进行建模,因此只有使用 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))
)
28.2. 3-D 函数¶
有许多函数被构建来计算 3-D 对象之间的关系。
ST_3DClosestPoint — 返回 g1 上最靠近 g2 的 3 维点。这是 3D 最短线的第一个点。
ST_3DDistance — 对于几何类型,返回两个几何体之间基于空间参考的 3 维笛卡尔最小距离(以投影单位表示)。
ST_3DDWithin — 对于 3d (z) 几何类型,如果两个几何体的 3d 距离在单位数范围内,则返回 true。
ST_3DDFullyWithin — 如果所有 3D 几何体都彼此之间的指定距离内,则返回 true。
ST_3DIntersects — 如果几何体在 3d 中“空间相交”,则返回 TRUE - 仅适用于点和线字符串。
ST_3DLongestLine — 返回两个几何体之间的 3 维最长线。
ST_3DMaxDistance — 对于几何类型,返回两个几何体之间基于空间参考的 3 维笛卡尔最大距离(以投影单位表示)。
ST_3DShortestLine — 返回两个几何体之间的 3 维最短线。
例如,我们可以使用 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
28.3. N-D 索引¶
一旦您拥有更高维度的數據,对它进行索引可能是有意义的。但是,在应用多维索引之前,您应该仔细考虑数据在所有维度上的分布。
索引只有在它们允许数据库大幅减少 WHERE 条件返回的行数时才有用。为了使更高维度的索引有用,数据必须覆盖该维度的大范围,相对于您正在构建的查询类型。
一组 DEM 点可能不是 3-D 索引的良好候选者,因为查询通常会提取 2-D 点框,很少尝试选择 Z 切片点。
一组 X/Y/T 空间中的 GPS 轨迹可能是 3-D 索引的良好候选者,如果 GPS 轨迹在所有维度上频繁地相互重叠(例如,在不同时间重复行驶相同的路线),因为数据集中所有维度都会存在很大的可变性。
您可以对任何维度的(甚至混合维度的)数据创建多维索引。例如,要创建对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 (3 3 3)'::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索引运算符替换为&&&
运算符。
-- 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索引。