第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 的三维与曲线几何:

  1. 3D 几何类型:XYZ、XYM、XYZM 坐标
  2. 3D 空间操作:距离、长度、面积计算
  3. SFCGAL 扩展:高级 3D 分析功能
  4. 曲线几何:圆弧、复合曲线、曲线多边形
  5. DEM 分析:坡度、坡向、等值线
  6. 点云处理:pointcloud 扩展

14.8 下一步

在下一章中,我们将学习与 GeoServer 集成,包括:

  • GeoServer 数据源配置
  • 图层发布
  • 样式设置
  • 性能优化

相关资源

posted @ 2025-12-29 10:54  我才是银古  阅读(5)  评论(0)    收藏  举报