第14章-三维与曲线几何
第14章:三维与曲线几何
14.1 三维几何支持
PostGIS 提供了完整的三维几何支持,包括存储、查询和分析 3D 数据的能力。
14.1.1 3D 几何类型
-- 3D 点 (XYZ)
SELECT ST_AsText(ST_GeomFromText('POINT Z(1 2 3)'));
-- 带测量值的点 (XYM)
SELECT ST_AsText(ST_GeomFromText('POINT M(1 2 3)'));
-- 4D 点 (XYZM)
SELECT ST_AsText(ST_GeomFromText('POINT ZM(1 2 3 4)'));
-- 3D 线
SELECT ST_AsText(ST_GeomFromText('LINESTRING Z(0 0 0, 1 1 1, 2 2 2)'));
-- 3D 多边形
SELECT ST_AsText(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0, 0 1 0, 0 0 0))'));
-- 3D 多面体表面
SELECT ST_AsText(ST_GeomFromText('POLYHEDRALSURFACE Z(
((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
((0 0 0, 0 0 1, 0 1 1, 0 1 0, 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 1 0, 1 0 0, 1 0 1, 1 1 1)),
((1 1 1, 0 1 1, 0 1 0, 1 1 0, 1 1 1))
)'));
-- TIN (不规则三角网)
SELECT ST_AsText(ST_GeomFromText('TIN Z(
((0 0 0, 0 1 0, 1 0 0, 0 0 0)),
((1 0 0, 0 1 0, 1 1 0, 1 0 0))
)'));
14.1.2 3D 坐标访问
-- 获取 Z 坐标
SELECT ST_Z(ST_GeomFromText('POINT Z(1 2 3)')); -- 3
-- 获取 M 值
SELECT ST_M(ST_GeomFromText('POINT M(1 2 3)')); -- 3
-- 获取 4D 坐标
WITH p AS (SELECT ST_GeomFromText('POINT ZM(1 2 3 4)') AS geom)
SELECT ST_X(geom), ST_Y(geom), ST_Z(geom), ST_M(geom) FROM p;
-- 获取 Z 范围
SELECT ST_ZMin(geom), ST_ZMax(geom)
FROM (SELECT ST_GeomFromText('LINESTRING Z(0 0 0, 1 1 10, 2 2 5)') AS geom) t;
-- 获取 M 范围
SELECT ST_MMin(geom), ST_MMax(geom)
FROM (SELECT ST_GeomFromText('LINESTRING M(0 0 0, 1 1 100, 2 2 50)') AS geom) t;
14.1.3 3D 几何构造
-- 创建 3D 点
SELECT ST_MakePoint(1, 2, 3);
SELECT ST_SetSRID(ST_MakePoint(116.4, 39.9, 45.5), 4326);
-- 创建 3D 线
SELECT ST_MakeLine(ARRAY[
ST_MakePoint(0, 0, 0),
ST_MakePoint(1, 1, 10),
ST_MakePoint(2, 2, 20)
]);
-- 从 2D 几何添加 Z 值
SELECT ST_Force3D(ST_MakePoint(1, 2), 100);
-- 设置所有点的 Z 值
SELECT ST_SetZ(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)'), 100);
-- 强制转换维度
SELECT ST_Force2D(ST_GeomFromText('POINT Z(1 2 3)')); -- 丢弃 Z
SELECT ST_Force3D(ST_GeomFromText('POINT(1 2)')); -- 添加 Z=0
SELECT ST_Force3DZ(ST_GeomFromText('POINT(1 2)')); -- 添加 Z=0
SELECT ST_Force3DM(ST_GeomFromText('POINT(1 2)')); -- 添加 M=0
SELECT ST_Force4D(ST_GeomFromText('POINT(1 2)')); -- 添加 Z=0, M=0
14.2 3D 空间操作
14.2.1 3D 距离计算
-- 3D 距离
SELECT ST_3DDistance(
ST_GeomFromText('POINT Z(0 0 0)'),
ST_GeomFromText('POINT Z(1 1 1)')
); -- √3 ≈ 1.732
-- 3D 点到线的距离
SELECT ST_3DDistance(
ST_GeomFromText('POINT Z(0 0 1)'),
ST_GeomFromText('LINESTRING Z(0 0 0, 2 0 0)')
); -- 1
-- 3D 最近点
SELECT ST_3DClosestPoint(
ST_GeomFromText('POINT Z(0 0 1)'),
ST_GeomFromText('LINESTRING Z(0 0 0, 2 0 0)')
);
-- 3D 最短线
SELECT ST_3DShortestLine(
ST_GeomFromText('POINT Z(0 0 1)'),
ST_GeomFromText('LINESTRING Z(0 0 0, 2 0 0)')
);
-- 3D 相交判断
SELECT ST_3DIntersects(
ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0, 0 1 0, 0 0 0))'),
ST_GeomFromText('LINESTRING Z(0.5 0.5 -1, 0.5 0.5 1)')
); -- true
14.2.2 3D 长度和面积
-- 3D 线长度
SELECT ST_3DLength(ST_GeomFromText('LINESTRING Z(0 0 0, 1 0 0, 1 1 0, 1 1 1)')); -- 3
-- 3D 周长
SELECT ST_3DPerimeter(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0, 0 1 0, 0 0 0))'));
-- 3D 面积(投影面积)
SELECT ST_Area(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0.5, 0 1 0.5, 0 0 0))'));
14.2.3 3D 几何操作
-- 3D 边界框
SELECT ST_3DExtent(geom) FROM spatial_3d;
-- 3D 质心
SELECT ST_3DCentroid(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 1, 0 1 1, 0 0 0))'));
-- 3D 相交
SELECT ST_3DIntersection(geom1, geom2) FROM ...; -- 需要 SFCGAL
-- 3D 差集
SELECT ST_3DDifference(geom1, geom2) FROM ...; -- 需要 SFCGAL
-- 3D 并集
SELECT ST_3DUnion(geom1, geom2) FROM ...; -- 需要 SFCGAL
14.3 SFCGAL 高级 3D 功能
14.3.1 启用 SFCGAL
-- 创建 SFCGAL 扩展
CREATE EXTENSION postgis_sfcgal;
-- 查看版本
SELECT postgis_sfcgal_version();
-- 查看支持的函数
\df *sfcgal*
14.3.2 SFCGAL 3D 函数
-- 3D 凸包
SELECT ST_3DConvexHull(ST_Collect(geom)) FROM points_3d;
-- 3D 交集
SELECT ST_3DIntersection(
ST_GeomFromText('POLYHEDRALSURFACE Z(...)'),
ST_GeomFromText('POLYGON Z(...)')
);
-- 3D 差集
SELECT ST_3DDifference(geom1, geom2);
-- 3D 并集
SELECT ST_3DUnion(geom1, geom2);
-- 体积计算
SELECT ST_Volume(ST_Extrude(
ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
0, 0, 10 -- 拉伸方向
));
-- 3D 面积
SELECT ST_3DArea(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0.5, 0 1 0.5, 0 0 0))'));
-- 实体几何检测
SELECT ST_IsSolid(geom) FROM buildings_3d;
-- 生成实体
SELECT ST_MakeSolid(ST_GeomFromText('POLYHEDRALSURFACE Z(...)'));
14.3.3 几何拉伸
-- 2D 多边形拉伸为 3D 实体
SELECT ST_Extrude(
ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
0, 0, 10 -- dx, dy, dz
);
-- 建筑物高度拉伸
SELECT
building_id,
ST_Extrude(footprint, 0, 0, height) AS building_3d
FROM buildings;
-- 带属性的拉伸
SELECT
name,
ST_Extrude(geom, 0, 0, floor_count * 3) AS building_solid
FROM buildings
WHERE floor_count > 0;
14.3.4 三角剖分
-- Delaunay 三角剖分
SELECT ST_DelaunayTriangles(ST_Collect(geom)) FROM survey_points;
-- 约束 Delaunay 三角剖分
SELECT ST_ConstrainedDelaunayTriangles(
ST_Collect(point_geom),
constraint_line_geom
);
-- TIN 生成
SELECT ST_AsTIN(ST_DelaunayTriangles(ST_Collect(geom), 0, 2))
FROM dem_points;
-- 三角剖分类型
-- flags: 0=多边形, 1=TIN, 2=仅边
SELECT ST_DelaunayTriangles(geom, 0.0, 0); -- 返回多边形
SELECT ST_DelaunayTriangles(geom, 0.0, 1); -- 返回线
SELECT ST_DelaunayTriangles(geom, 0.0, 2); -- 返回 TIN
14.4 曲线几何
14.4.1 曲线几何类型
-- 圆弧字符串 (CIRCULARSTRING)
SELECT ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)');
-- 复合曲线 (COMPOUNDCURVE)
SELECT ST_GeomFromText('COMPOUNDCURVE(
CIRCULARSTRING(0 0, 1 1, 2 0),
(2 0, 3 0, 3 1)
)');
-- 曲线多边形 (CURVEPOLYGON)
SELECT ST_GeomFromText('CURVEPOLYGON(
CIRCULARSTRING(0 0, 2 0, 2 2, 0 2, 0 0)
)');
-- 多曲面 (MULTISURFACE)
SELECT ST_GeomFromText('MULTISURFACE(
CURVEPOLYGON(CIRCULARSTRING(0 0, 2 0, 2 2, 0 2, 0 0)),
((4 4, 5 4, 5 5, 4 5, 4 4))
)');
-- 多曲线 (MULTICURVE)
SELECT ST_GeomFromText('MULTICURVE(
CIRCULARSTRING(0 0, 1 1, 2 0),
(3 0, 4 1, 5 0)
)');
14.4.2 曲线转换
-- 曲线转线段
SELECT ST_CurveToLine(
ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)'),
32 -- 每四分之一圆的点数
);
-- 控制转换精度
SELECT ST_CurveToLine(
ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)'),
32, -- 每四分之一圆的点数
1, -- 类型: 0=自适应, 1=每弧段固定点数, 2=最大偏差
0.01 -- 最大偏差(类型2时使用)
);
-- 线段逼近曲线
SELECT ST_LineToCurve(ST_Buffer(ST_MakePoint(0, 0), 1));
-- 检查是否包含曲线
SELECT ST_HasArc(ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)')); -- true
SELECT ST_HasArc(ST_GeomFromText('LINESTRING(0 0, 1 1, 2 0)')); -- false
14.4.3 曲线操作
-- 曲线长度
SELECT ST_Length(ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)'));
-- 曲线面积(曲线多边形)
SELECT ST_Area(ST_GeomFromText('CURVEPOLYGON(CIRCULARSTRING(0 0, 2 0, 2 2, 0 2, 0 0))'));
-- 曲线缓冲区
SELECT ST_Buffer(ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)'), 0.1);
-- 曲线与其他几何的交集
SELECT ST_Intersection(
ST_GeomFromText('CIRCULARSTRING(0 0, 1 1, 2 0)'),
ST_MakeEnvelope(0.5, 0, 1.5, 1)
);
14.5 DEM 分析
14.5.1 坡度和坡向
-- 计算坡度(使用栅格)
SELECT ST_Slope(rast, 1, '32BF') FROM dem;
-- 计算坡向
SELECT ST_Aspect(rast, 1, '32BF') FROM dem;
-- 山体阴影
SELECT ST_HillShade(rast, 1, '32BF', 315, 45, 1) FROM dem;
-- 参数: 栅格, 波段, 输出类型, 方位角, 高度角, 高程夸张因子
-- 基于点云的坡度计算
WITH points AS (
SELECT id, ST_X(geom) AS x, ST_Y(geom) AS y, ST_Z(geom) AS z
FROM dem_points
)
SELECT
p.id,
DEGREES(ATAN(SQRT(
POWER((p2.z - p1.z) / (p2.x - p1.x), 2) +
POWER((p3.z - p1.z) / (p3.y - p1.y), 2)
))) AS slope_deg
FROM points p
JOIN points p1 ON ST_DWithin(ST_MakePoint(p.x, p.y), ST_MakePoint(p1.x, p1.y), 10)
JOIN points p2 ON ...
JOIN points p3 ON ...;
14.5.2 等值线生成
-- 从栅格生成等值线
SELECT ST_Contour(rast, 1,
interval := 100, -- 等值线间距
smooth := true -- 平滑
) FROM dem;
-- 从点云生成等值线
WITH triangles AS (
SELECT ST_DelaunayTriangles(ST_Collect(geom), 0, 2) AS tin
FROM dem_points
)
SELECT ST_Contour(tin, 100) FROM triangles;
-- 生成特定高程的等值线
SELECT (ST_Contour(rast, 1, values := ARRAY[100, 200, 300, 400, 500])).*
FROM dem;
14.5.3 视域分析
-- 简单视域分析(基于直线)
CREATE OR REPLACE FUNCTION check_visibility(
observer geometry,
target geometry,
dem_table text
) RETURNS boolean AS $$
DECLARE
sight_line geometry;
profile_points geometry[];
observer_z float;
target_z float;
point_z float;
i int;
BEGIN
-- 创建视线
sight_line := ST_MakeLine(observer, target);
-- 获取观察点和目标点高程
EXECUTE format('SELECT ST_Value(rast, $1) FROM %I WHERE ST_Intersects(rast, $1)', dem_table)
INTO observer_z USING observer;
EXECUTE format('SELECT ST_Value(rast, $1) FROM %I WHERE ST_Intersects(rast, $1)', dem_table)
INTO target_z USING target;
-- 检查视线路径上的高程
FOR i IN 1..100 LOOP
-- 沿视线插值点
-- 检查地形是否阻挡视线
-- ...
END LOOP;
RETURN true;
END;
$$ LANGUAGE plpgsql;
14.6 点云处理
14.6.1 pointcloud 扩展
-- 安装点云扩展
CREATE EXTENSION pointcloud;
CREATE EXTENSION pointcloud_postgis;
-- 创建点云表
CREATE TABLE lidar_data (
id SERIAL PRIMARY KEY,
pa pcpatch(1) -- 点云块
);
-- 点云格式定义
INSERT INTO pointcloud_formats (pcid, srid, schema) VALUES (
1, 4326,
'<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1">
<pc:dimension><pc:position>1</pc:position><pc:name>X</pc:name><pc:size>4</pc:size><pc:type>float</pc:type></pc:dimension>
<pc:dimension><pc:position>2</pc:position><pc:name>Y</pc:name><pc:size>4</pc:size><pc:type>float</pc:type></pc:dimension>
<pc:dimension><pc:position>3</pc:position><pc:name>Z</pc:name><pc:size>4</pc:size><pc:type>float</pc:type></pc:dimension>
<pc:dimension><pc:position>4</pc:position><pc:name>Intensity</pc:name><pc:size>2</pc:size><pc:type>uint16_t</pc:type></pc:dimension>
</pc:PointCloudSchema>'
);
14.6.2 点云操作
-- 获取点云统计信息
SELECT PC_Summary(pa) FROM lidar_data;
-- 获取点数
SELECT PC_NumPoints(pa) FROM lidar_data;
-- 点云转几何
SELECT PC_EnvelopeGeometry(pa) FROM lidar_data; -- 边界框
SELECT ST_Collect(PC_AsGeometry(pa)) FROM lidar_data; -- 转为多点
-- 点云过滤
SELECT PC_FilterBetween(pa, 'Z', 100, 200) FROM lidar_data; -- 按高程过滤
SELECT PC_FilterEquals(pa, 'Classification', 2) FROM lidar_data; -- 按分类过滤
-- 点云合并
SELECT PC_Union(pa) FROM lidar_data WHERE ST_Intersects(PC_EnvelopeGeometry(pa), query_geom);
-- 点云裁剪
SELECT PC_Intersection(pa, polygon_geom) FROM lidar_data;
14.7 本章小结
本章详细介绍了 PostGIS 的三维与曲线几何:
- 3D 几何类型:XYZ、XYM、XYZM 坐标
- 3D 空间操作:距离、长度、面积计算
- SFCGAL 扩展:高级 3D 分析功能
- 曲线几何:圆弧、复合曲线、曲线多边形
- DEM 分析:坡度、坡向、等值线
- 点云处理:pointcloud 扩展
14.8 下一步
在下一章中,我们将学习与 GeoServer 集成,包括:
- GeoServer 数据源配置
- 图层发布
- 样式设置
- 性能优化
相关资源:

浙公网安备 33010602011771号