泰州市网站建设_网站建设公司_过渡效果_seo优化
2025/12/29 10:56:19 网站建设 项目流程

第08章:几何输出函数

8.1 几何输出函数概述

PostGIS 提供了多种几何输出函数,用于将几何对象转换为各种格式的文本或二进制表示。这些函数对于数据交换、可视化和与其他系统集成至关重要。

8.1.1 输出格式分类

┌─────────────────────────────────────────────────────────────┐
│                    几何输出格式分类                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  文本格式                                                    │
│  ├── WKT (Well-Known Text)         - OGC 标准文本格式       │
│  ├── EWKT (Extended WKT)           - PostGIS 扩展文本格式   │
│  ├── GeoJSON                       - JSON 格式              │
│  ├── GML (Geography Markup)        - XML 格式               │
│  ├── KML (Keyhole Markup)          - Google Earth 格式      │
│  └── SVG (Scalable Vector)         - 可缩放矢量图形         │
│                                                             │
│  二进制格式                                                  │
│  ├── WKB (Well-Known Binary)       - OGC 标准二进制格式     │
│  ├── EWKB (Extended WKB)           - PostGIS 扩展二进制格式 │
│  ├── TWKB (Tiny WKB)               - 紧凑二进制格式         │
│  └── MVT (Mapbox Vector Tile)      - 矢量瓦片格式           │
│                                                             │
│  其他格式                                                    │
│  ├── Encoded Polyline              - Google 编码折线        │
│  ├── GeoHash                       - 空间哈希               │
│  └── LatLonText                    - 经纬度文本             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

8.2 WKT 输出

8.2.1 ST_AsText (WKT)

-- 基本用法
SELECT ST_AsText(ST_MakePoint(116.4, 39.9));
-- POINT(116.4 39.9)SELECT ST_AsText(ST_MakeLine(ST_MakePoint(0, 0), ST_MakePoint(1, 1)));
-- LINESTRING(0 0,1 1)SELECT ST_AsText(ST_MakeEnvelope(0, 0, 1, 1));
-- POLYGON((0 0,0 1,1 1,1 0,0 0))-- 3D 几何
SELECT ST_AsText(ST_MakePoint(116.4, 39.9, 45.5));
-- POINT Z (116.4 39.9 45.5)-- 带 M 值
SELECT ST_AsText(ST_MakePointM(116.4, 39.9, 100));
-- POINT M (116.4 39.9 100)-- 4D 几何
SELECT ST_AsText(ST_GeomFromText('POINT ZM(116.4 39.9 45.5 100)'));
-- POINT ZM (116.4 39.9 45.5 100)-- 控制精度(小数位数)
SELECT ST_AsText(ST_MakePoint(116.40740001, 39.90420001), 4);
-- POINT(116.4074 39.9042)SELECT ST_AsText(ST_MakePoint(116.40740001, 39.90420001), 2);
-- POINT(116.41 39.9)-- 多几何类型
SELECT ST_AsText(ST_Collect(ST_MakePoint(0, 0),ST_MakePoint(1, 1)
));
-- MULTIPOINT((0 0),(1 1))

8.2.2 ST_AsEWKT (Extended WKT)

-- EWKT 包含 SRID 信息
SELECT ST_AsEWKT(ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326));
-- SRID=4326;POINT(116.4 39.9)SELECT ST_AsEWKT(ST_SetSRID(ST_MakePoint(116.4, 39.9, 45.5), 4326));
-- SRID=4326;POINT Z (116.4 39.9 45.5)-- 控制精度
SELECT ST_AsEWKT(ST_SetSRID(ST_MakePoint(116.40740001, 39.90420001), 4326), 4);
-- SRID=4326;POINT(116.4074 39.9042)-- 与 ST_AsText 的区别
SELECT ST_AsText(geom) AS wkt,ST_AsEWKT(geom) AS ewkt
FROM poi LIMIT 1;
-- wkt: POINT(116.4 39.9)
-- ewkt: SRID=4326;POINT(116.4 39.9)

8.3 WKB 输出

8.3.1 ST_AsBinary (WKB)

-- 获取 WKB(十六进制显示)
SELECT ST_AsBinary(ST_MakePoint(116.4, 39.9));
-- 返回 bytea 类型-- 转换为十六进制字符串
SELECT encode(ST_AsBinary(ST_MakePoint(116.4, 39.9)), 'hex');-- 指定字节序
-- 'NDR': 小端序(默认)
-- 'XDR': 大端序
SELECT encode(ST_AsBinary(ST_MakePoint(0, 0), 'NDR'), 'hex');
SELECT encode(ST_AsBinary(ST_MakePoint(0, 0), 'XDR'), 'hex');-- WKB 不包含 SRID
SELECT ST_SRID(ST_GeomFromWKB(ST_AsBinary(ST_SetSRID(ST_MakePoint(0, 0), 4326))));
-- 0(SRID 丢失)

8.3.2 ST_AsEWKB (Extended WKB)

-- EWKB 包含 SRID
SELECT encode(ST_AsEWKB(ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326)), 'hex');-- 保留 SRID
SELECT ST_SRID(ST_GeomFromEWKB(ST_AsEWKB(ST_SetSRID(ST_MakePoint(0, 0), 4326))));
-- 4326-- 指定字节序
SELECT encode(ST_AsEWKB(ST_SetSRID(ST_MakePoint(0, 0), 4326), 'XDR'), 'hex');

8.3.3 ST_AsHEXEWKB

-- 直接返回十六进制字符串
SELECT ST_AsHEXEWKB(ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326));
-- 0101000020E610000066666666662D5D4066666666E6F34340-- 等价于
SELECT encode(ST_AsEWKB(ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326)), 'hex');

8.3.4 ST_AsTWKB (Tiny WKB)

-- TWKB 是一种紧凑的二进制格式
-- 适合网络传输和存储-- 基本用法
SELECT encode(ST_AsTWKB(ST_MakePoint(116.4, 39.9)), 'hex');-- 控制精度(XY 精度)
SELECT encode(ST_AsTWKB(ST_MakePoint(116.4074, 39.9042), 4), 'hex');  -- 4位小数
SELECT encode(ST_AsTWKB(ST_MakePoint(116.4074, 39.9042), 2), 'hex');  -- 2位小数-- 完整参数
-- ST_AsTWKB(geom, precision_xy, precision_z, precision_m, include_sizes, include_bboxes)
SELECT encode(ST_AsTWKB(ST_SetSRID(ST_MakePoint(116.4074, 39.9042, 45.5), 4326),6,    -- XY 精度(6位小数)2,    -- Z 精度0,    -- M 精度true, -- 包含大小信息true  -- 包含边界框
), 'hex');-- 比较不同格式的大小
SELECT pg_column_size(ST_AsBinary(geom)) AS wkb_size,pg_column_size(ST_AsEWKB(geom)) AS ewkb_size,pg_column_size(ST_AsTWKB(geom, 6)) AS twkb_size
FROM complex_polygons
LIMIT 5;-- TWKB 聚合
SELECT encode(ST_AsTWKB(array_agg(geom),ARRAY[id]::bigint[],  -- ID 数组6
), 'hex')
FROM poi
WHERE category = '餐饮';

8.4 GeoJSON 输出

8.4.1 ST_AsGeoJSON

-- 基本用法
SELECT ST_AsGeoJSON(ST_MakePoint(116.4, 39.9));
-- {"type":"Point","coordinates":[116.4,39.9]}SELECT ST_AsGeoJSON(ST_MakeLine(ST_MakePoint(0, 0), ST_MakePoint(1, 1)));
-- {"type":"LineString","coordinates":[[0,0],[1,1]]}SELECT ST_AsGeoJSON(ST_MakeEnvelope(0, 0, 1, 1));
-- {"type":"Polygon","coordinates":[[[0,0],[0,1],[1,1],[1,0],[0,0]]]}-- 控制精度
SELECT ST_AsGeoJSON(ST_MakePoint(116.40740001, 39.90420001), 4);
-- {"type":"Point","coordinates":[116.4074,39.9042]}-- 包含 CRS 信息
SELECT ST_AsGeoJSON(ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326), 15, 2);
-- {"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"coordinates":[116.4,39.9]}-- 参数说明
-- ST_AsGeoJSON(geom, maxdecimaldigits, options)
-- options 位掩码:
-- 0 = 无选项
-- 1 = 包含边界框
-- 2 = 使用短 CRS(EPSG:xxxx)
-- 4 = 使用长 CRS(urn:ogc:def:crs:EPSG::xxxx)
-- 8 = GeoJSON 规范严格模式-- 包含边界框
SELECT ST_AsGeoJSON(ST_MakeEnvelope(0, 0, 1, 1), 15, 1);
-- {"type":"Polygon","bbox":[0,0,1,1],"coordinates":[[[0,0],[0,1],[1,1],[1,0],[0,0]]]}-- 3D 几何
SELECT ST_AsGeoJSON(ST_MakePoint(116.4, 39.9, 45.5));
-- {"type":"Point","coordinates":[116.4,39.9,45.5]}

8.4.2 构建完整的 GeoJSON Feature

-- 创建 GeoJSON Feature
SELECT json_build_object('type', 'Feature','geometry', ST_AsGeoJSON(geom)::json,'properties', json_build_object('id', id,'name', name,'category', category)
)
FROM poi
WHERE id = 1;-- 创建 GeoJSON FeatureCollection
SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type', 'Feature','geometry', ST_AsGeoJSON(geom)::json,'properties', json_build_object('id', id,'name', name,'category', category)))
)
FROM poi
WHERE category = '餐饮';-- 使用 row_to_json 简化
SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type', 'Feature','geometry', ST_AsGeoJSON(geom, 6)::json,'properties', to_jsonb(t) - 'geom'))
)
FROM (SELECT id, name, category, geom FROM poi) t;

8.4.3 使用 jsonb 函数

-- 使用 jsonb 构建(更高效)
SELECT jsonb_build_object('type', 'FeatureCollection','features', jsonb_agg(jsonb_build_object('type', 'Feature','id', id,'geometry', ST_AsGeoJSON(geom)::jsonb,'properties', jsonb_build_object('name', name,'category', category)))
)
FROM poi
WHERE ST_Intersects(geom, ST_MakeEnvelope(116, 39, 117, 40, 4326));

8.5 GML 和 KML 输出

8.5.1 ST_AsGML

-- 基本 GML 输出
SELECT ST_AsGML(ST_MakePoint(116.4, 39.9));
-- <gml:Point><gml:coordinates>116.4,39.9</gml:coordinates></gml:Point>-- GML 3 格式
SELECT ST_AsGML(3, ST_MakePoint(116.4, 39.9));
-- <gml:Point><gml:pos>116.4 39.9</gml:pos></gml:Point>-- 控制精度
SELECT ST_AsGML(3, ST_MakePoint(116.40740001, 39.90420001), 4);-- 包含 SRID
SELECT ST_AsGML(3, ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326), 15, 1);
-- 添加 srsName 属性-- 完整参数
-- ST_AsGML(version, geom, maxdecimaldigits, options, nprefix, id)
SELECT ST_AsGML(3,                    -- GML 版本ST_SetSRID(ST_MakePoint(116.4, 39.9), 4326),6,                    -- 精度17,                   -- options: 1(srsName) + 16(namespace)'custom',             -- 命名空间前缀'point1'              -- ID
);-- options 位掩码:
-- 1 = 输出 srsName
-- 2 = 使用长 SRID URN
-- 4 = GML 3.2 格式
-- 16 = 声明命名空间
-- 32 = LineString 使用 srsDimension

8.5.2 ST_AsKML

-- 基本 KML 输出
SELECT ST_AsKML(ST_MakePoint(116.4, 39.9));
-- <Point><coordinates>116.4,39.9</coordinates></Point>-- 控制精度
SELECT ST_AsKML(ST_MakePoint(116.40740001, 39.90420001), 4);
-- <Point><coordinates>116.4074,39.9042</coordinates></Point>-- 3D 几何(KML 使用高程)
SELECT ST_AsKML(ST_MakePoint(116.4, 39.9, 45.5));
-- <Point><coordinates>116.4,39.9,45.5</coordinates></Point>-- 带名称前缀
SELECT ST_AsKML(ST_MakePoint(116.4, 39.9), 15, 'kml');
-- <kml:Point><kml:coordinates>116.4,39.9</kml:coordinates></kml:Point>-- 创建完整的 KML 文档
SELECT '<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"><Document><name>POI 数据</name>' ||
string_agg('<Placemark><name>' || name || '</name><description>' || COALESCE(category, '') || '</description>' ||ST_AsKML(geom) ||'</Placemark>',''
) ||'</Document>
</kml>'
FROM poi
WHERE category = '景点';

8.6 SVG 输出

8.6.1 ST_AsSVG

-- 基本 SVG 路径
SELECT ST_AsSVG(ST_MakePoint(116.4, 39.9));
-- cx="116.4" cy="-39.9"  (注意 Y 轴翻转)SELECT ST_AsSVG(ST_MakeLine(ST_MakePoint(0, 0), ST_MakePoint(1, 1)));
-- M 0 0 L 1 -1SELECT ST_AsSVG(ST_MakeEnvelope(0, 0, 1, 1));
-- M 0 0 L 0 -1 1 -1 1 0 Z-- 控制精度和相对/绝对路径
-- ST_AsSVG(geom, rel, maxdecimaldigits)
-- rel = 0: 绝对路径 (M, L)
-- rel = 1: 相对路径 (m, l)SELECT ST_AsSVG(ST_MakeEnvelope(0, 0, 1, 1), 0, 2);  -- 绝对路径
SELECT ST_AsSVG(ST_MakeEnvelope(0, 0, 1, 1), 1, 2);  -- 相对路径-- 创建 SVG 文档
WITH bounds AS (SELECT ST_XMin(ST_Collect(geom)) AS min_x,ST_YMin(ST_Collect(geom)) AS min_y,ST_XMax(ST_Collect(geom)) AS max_x,ST_YMax(ST_Collect(geom)) AS max_yFROM districts
),
svg_paths AS (SELECT id, name, ST_AsSVG(geom, 0, 2) AS pathFROM districts
)
SELECT '<svg xmlns="http://www.w3.org/2000/svg" viewBox="' || min_x || ' ' || (-max_y) || ' ' || (max_x - min_x) || ' ' || (max_y - min_y) || '">' ||string_agg('<path d="' || path || '" fill="steelblue" stroke="white" stroke-width="0.01"/>', '') ||'</svg>'
FROM bounds, svg_paths
GROUP BY min_x, min_y, max_x, max_y;

8.7 其他输出格式

8.7.1 ST_AsEncodedPolyline

-- Google 编码折线(用于 Google Maps API)
SELECT ST_AsEncodedPolyline(ST_GeomFromText('LINESTRING(-120.2 38.5,-120.95 40.7,-126.453 43.252)', 4326)
);
-- _p~iF~ps|U_ulLnnqC_mqNvxq`@-- 控制精度(默认 5)
SELECT ST_AsEncodedPolyline(ST_GeomFromText('LINESTRING(-120.2 38.5,-120.95 40.7)', 4326),6  -- 6 位精度
);-- 解码
SELECT ST_AsText(ST_LineFromEncodedPolyline('_p~iF~ps|U_ulLnnqC_mqNvxq`@'));

8.7.2 ST_GeoHash

-- 生成 GeoHash
SELECT ST_GeoHash(ST_MakePoint(116.4074, 39.9042));
-- wx4g0ffe3d (默认完整精度)-- 控制精度
SELECT ST_GeoHash(ST_MakePoint(116.4074, 39.9042), 8);
-- wx4g0ffeSELECT ST_GeoHash(ST_MakePoint(116.4074, 39.9042), 5);
-- wx4g0-- 从 GeoHash 创建几何(边界框)
SELECT ST_AsText(ST_GeomFromGeoHash('wx4g0'));
-- POLYGON((116.3671875 39.8583984375, ...))-- 获取 GeoHash 的点(中心点)
SELECT ST_AsText(ST_PointFromGeoHash('wx4g0'));-- GeoHash 网格分析
SELECT ST_GeoHash(geom, 5) AS geohash,COUNT(*) AS poi_count
FROM poi
GROUP BY ST_GeoHash(geom, 5)
ORDER BY poi_count DESC;

8.7.3 ST_AsLatLonText

-- 度分秒格式
SELECT ST_AsLatLonText(ST_MakePoint(116.4074, 39.9042));
-- 39°54'15.120"N 116°24'26.640"E-- 自定义格式
SELECT ST_AsLatLonText(ST_MakePoint(116.4074, 39.9042), 'D°M''S.SSS"');
-- 39°54'15.120" 116°24'26.640"SELECT ST_AsLatLonText(ST_MakePoint(116.4074, 39.9042), 'D.DDD°');
-- 39.904° 116.407°

8.7.4 ST_AsX3D

-- X3D 格式(3D 可视化)
SELECT ST_AsX3D(ST_MakePoint(116.4, 39.9, 45.5));
-- 116.4 39.9 45.5SELECT ST_AsX3D(ST_GeomFromText('POLYGON Z((0 0 0, 1 0 0, 1 1 0, 0 1 0, 0 0 0))'));-- 控制精度
SELECT ST_AsX3D(ST_MakePoint(116.40740001, 39.90420001, 45.5), 4);

8.8 MVT 输出

8.8.1 ST_AsMVTGeom

-- 准备 MVT 几何(坐标转换到瓦片坐标系)
SELECT ST_AsMVTGeom(geom,ST_TileEnvelope(14, 13527, 6214),  -- z/x/y 瓦片边界4096,  -- extent(瓦片像素尺寸)0,     -- buffertrue   -- clip to tile
) AS mvt_geom
FROM poi
WHERE geom && ST_TileEnvelope(14, 13527, 6214);

8.8.2 ST_AsMVT

-- 生成 MVT 瓦片
SELECT ST_AsMVT(tile, 'poi') AS mvt
FROM (SELECT id,name,category,ST_AsMVTGeom(geom,ST_TileEnvelope(14, 13527, 6214),4096,64,true) AS geomFROM poiWHERE geom && ST_TileEnvelope(14, 13527, 6214)
) AS tile;-- 创建 MVT 瓦片函数
CREATE OR REPLACE FUNCTION get_mvt_tile(z INT, x INT, y INT)
RETURNS bytea AS $$
DECLAREtile_bounds geometry;mvt bytea;
BEGINtile_bounds := ST_TileEnvelope(z, x, y);SELECT ST_AsMVT(tile, 'poi', 4096, 'geom') INTO mvtFROM (SELECT id,name,category,ST_AsMVTGeom(geom,tile_bounds,4096,64,true) AS geomFROM poiWHERE geom && tile_bounds) AS tile;RETURN mvt;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;-- 使用
SELECT get_mvt_tile(14, 13527, 6214);-- 多图层 MVT
SELECT ST_AsMVT(poi_layer, 'poi') || ST_AsMVT(road_layer, 'roads') AS mvt
FROM (SELECT id, name, ST_AsMVTGeom(geom, bounds, 4096, 64, true) AS geomFROM poi, (SELECT ST_TileEnvelope(14, 13527, 6214) AS bounds) bWHERE geom && bounds
) poi_layer,
(SELECT id, name, ST_AsMVTGeom(geom, bounds, 4096, 64, true) AS geomFROM roads, (SELECT ST_TileEnvelope(14, 13527, 6214) AS bounds) bWHERE geom && bounds
) road_layer;

8.9 格式比较与选择

8.9.1 格式特性对比

格式 人类可读 大小 SRID 3D支持 用途
WKT 调试、日志
EWKT 数据交换
WKB 程序间传输
EWKB PostGIS 内部
TWKB 网络传输
GeoJSON 部分 Web API
GML 很大 OGC 服务
KML Google Earth
MVT 矢量瓦片

8.9.2 选择建议

-- Web API(推荐 GeoJSON)
SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type', 'Feature','geometry', ST_AsGeoJSON(ST_Simplify(geom, 0.0001), 6)::json,'properties', json_build_object('id', id, 'name', name)))
)
FROM districts;-- 数据备份(推荐 EWKT 或 EWKB)
COPY (SELECT id, name, ST_AsEWKT(geom) AS geomFROM spatial_data
) TO '/tmp/backup.csv' WITH CSV HEADER;-- 移动应用(推荐 TWKB)
SELECT id, name, encode(ST_AsTWKB(geom, 5), 'base64') AS geom
FROM poi
WHERE category = '餐饮';-- 地图瓦片(推荐 MVT)
SELECT get_mvt_tile(z, x, y);-- Google Earth(推荐 KML)
SELECT ST_AsKML(geom) FROM poi;

8.10 本章小结

本章详细介绍了 PostGIS 的几何输出函数:

  1. WKT 输出:ST_AsText、ST_AsEWKT
  2. WKB 输出:ST_AsBinary、ST_AsEWKB、ST_AsTWKB
  3. GeoJSON 输出:ST_AsGeoJSON 及 FeatureCollection 构建
  4. GML/KML 输出:ST_AsGML、ST_AsKML
  5. SVG 输出:ST_AsSVG
  6. 其他格式:编码折线、GeoHash、X3D
  7. MVT 输出:矢量瓦片生成

8.11 下一步

在下一章中,我们将学习空间关系函数,包括:

  • 拓扑关系判断
  • 距离关系
  • 方向关系
  • DE-9IM 模型

相关资源

  • PostGIS 输出函数
  • GeoJSON 规范
  • KML 参考
  • MVT 规范

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询