输出函数

wkt和wkb

wkt和wkb是空间对象最常见的OGC文本和二进制格式。事实上,包括PostGIS在内的许多空间数据库都是以基于wkb标准的格式存储几何数据。

以wkt格式输出几何图形的两个函数是ST_AsText和ST_AsEWKT。

以wkb格式输出集合图形的两个函数是ST_AsBinary和ST_AsEWKB。

Keyhole

用于导出到KML的PostGIS几何和地理函数是ST_AsKML。该函数的默认输出为第二版KML,具有15位精度。ST_AsKML不是一个函数,而是多个具有相同名称但不接受不同参数的函数。该函数的其它变体允许更改目标KML版本和精度级别。

KML的空间参考系统始终是WGS 84 lon/lat(SRID 4326)。只要集合图形使用已知的SRID,ST_AsKML就会自动转换为SRID 4326。

ST_AsKML支持2D和3D基本几何图形,但在到处曲线几何图形、几何图形集合、多面图表面或TIN时会报错。尽管ST_AsKML接受包含M坐标的几何图形,但它不会输出M坐标。

地理标记语言

地理标记语言是一种基于XML的格式,它是用于geometry和geography类型的OGC定义传输格式。在网络要素服务中,它通常用于输出查询的列。

用于导出到DML的PostGIS函数是ST_AsGML,它同时支持geometry和geography空间类型。ST_AsGML由许多变体,可以控制GML版本和精度。该函数支持的GML版本为2.1.2和3.1.1。传入参数2和3区分,如果未传入版本参数,则默认使用的是2.1.2。另外两个参数控制有效位数和是否使用短crs。

ST_AsGML支持2D和3D的几何图形和几何图形集合。如果几何图形有M坐标,M坐标将会被丢弃。

几何JavaScript对象表示法

几何JavaScript对象表示法是一种基于JavaScript对象表示发的格式。GeoJSON为面向Ajax的应用程序(如OpenLayers和Leaflet)而改变,因为它的输出表示法是JavaScript格式的。JSON是JavaScript数据结构中的标准对象表示形式,而GeoJSON通过添加存储地理对象的规范来扩展JSON。

对于将geography和geometry数据类型导出到GeoJSON的PostGIS函数是ST_AsGeoJSON。

ST_AsGeoJSON支持2D图形、基本3D图形和几何图形集合。它会丢弃M坐标,处理TIN、多面体表面和曲线集合图形时会出错。

可缩放矢量图形

用于导出到SVG的PostGIS函数是ST_AsSVG。函数只能输出内有SRID Z M坐标的2D几何图形,不能输出曲线几何图形。

Mapbox矢量切片和协议缓冲区

ST_AsGeobuf是一个聚合函数,它将一组PostgreSQL数据行编码为PBF格式,但不涉及切片。

ST_TileEnvelope是PostGIS 3中导入,它以tileZoom、tileX、tileY(X Y Z切片系统,通常由栅格切片使用)作为输入,返回以这些参数为边界的正方形几何图形。如果不使用可选参数覆盖它,它返回的默认空间参考系统是Web墨卡托。

ST_AsMVTGeom是一个将几何图形剪裁到指定的边界并将其简化为256*256分辨率的函数,不过可以使用buffer参数更改分辨率大小。此函数经常与ST_TileEnvelope搭配使用,ST_TileEnvelope计算边界并将边界提供给ST_AsMVTGeom。

ST_AsMVT是一个聚合函数,它获取一组行,将其裁剪到指定范围,并返回MVT格式编码的二进制blob类型数据。此函数经常与ST_AsMVTGeom搭配使用,ST_AsMVTGeom返回经过裁剪并简化为输入切片尺寸的几何图形。

虽然ST_TileEnvelope被设计为制作MVT切片的辅助函数,但通过将其与PostGIS栅格函数ST_Clip和ST_Transform相结合,同样可以轻松地使用它创建栅格切片。

TinyWKB

Tiny WKB是PostGIS2.2引入的另一种用于Web绘图的格式。与MVT格式类似,它是一种压缩二进制格式,但他基于WKB格式。类似于GeoJSON/GML/KML,它处理整个几何图形。

ST_AsTWKB是将PostGIS几何图形转换为TWKB二进制的函数。

ST_GeomFormTWKB函数将TWKB二进制格式作为输出,并将其中的几何图形部分以PostGIS几何图形的形式返回。

可扩展3D图形

可扩展3D(X3D)图形是一种ISO XML格式,用于定义3D空间中的对象。它诞生与旧的虚拟现实建模语言(VRML)。ST_AsX3D函数只支持几何图形,不支持地理类型——它主要关注3D几何图形。除了ST_AsGML之外,ST_AsX3D是唯一支持TIN和多面体表面几何图形的格式函数。

输出函数示例

 SELECT
 ST_AsGML(X.geom,5) as GML,
 ST_AsKML(X.geom,5) As KML,
 ST_AsGeoJSON(X,'geom', 5) As GeoJSON,
 ST_AsSVG(X.geom,0,5) As SVG_Absolute,
 ST_AsSVG(X.geom,1,5) As SVG_Relative,
 ST_AsX3D(X.geom,6) As X3D,
 ST_AsTWKB(X.geom,5) AS TWKB,
 ST_AsGeobuf(X, 'geom') OVER() AS PBF
 FROM
 (SELECT
 'My street' As label, ST_GeomFromText('LINESTRING(2 48 1,0 51 
1)',4326) As geom
 ) X;

Geohash

Geohash是一种有损的经纬度地理编码系统。这意味着与其说它是用来视觉呈现的,不如说它是一种用于方便交换坐标的工具,或者一个廉价的索引策略。

PostGIS使用函数ST_Geohash将数据输出为Geohash。ST_GeoHash始终输出WGS 84 lon/lat坐标,并且数据源必须使用已知的SRID,这样ST_GeoHash可以在输出的时候自动进行转换。ST_GeoHash支持曲线几何图形,但不支持M或Z坐标。

对于点来说,Geohash输最精确的。如果输出点以外的任何内容,ST_GeoHash将输出与几何图形的边界框相对于的哈希值。边界框越大,哈希值越短。事实上对于一些大的区域,Geohash将直接放弃,什么也不输出。

构造函数

使用文本和二进制格式创建几何图形

ST_GeomFormText

WKT表示是描述几何图形的常用方法,ST_GeomFormText函数可以利用WKT构建几何图形。在PostGIS 2.0之前,此函数仅接受2D几何图形;从第二版开始,它接受所有维度的几何图形。

 SELECT * INTO ch06.unconstrained_geoms
 FROM (
 VALUES
 (ST_GeomFromText('POINT(-100 28 1)',4326)),
 (ST_GeomFromText('LINESTRING(-80 28 1,-90 29 1)',4326)),
 (ST_GeomFromText('POLYGONZ((10 28 1,9 29 1,7 30 1,10 28 1))')),
 (ST_GeomFromText(
 'POLYHEDRALSURFACE(
 ((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),
 ((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),
 ((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),
 ((1 1 0,1 1 1,1 0 1,1 0 0,1 1 0)),
 ((0 1 0,0 1 1,1 1 1,1 1 0,0 1 0)),
 ((0 0 1,1 0 1,1 1 1,0 1 1,0 0 1))
 )'
 ))
 ) As z(geom);
 SELECT geom::geometry(LineString,4326) INTO ch06.constrained_geoms
 FROM (
 VALUES
 (ST_GeomFromText('LINESTRING(-80 28,-90 29)', 4326)),
 (ST_GeomFromText('LINESTRING(10 28, 9 29, 7 30)', 4326 ))
 ) As x(geom)

ST_GeoFromWKB和ST_GeoFromEWKB

通常,需要从一级以二进制表示形式存储几何图形的客户机应用程序中导入数据。这就是ST_GeomFromWKB和ST_GeomFromEWKB函数发挥作用的地方。

这两个函数接受字节数组而不是文本字符串,PostGIS几何类型派生自字节数组。从这个意义上将,将字节数组用作输入或输出格式时不会导致数据损失。

任何文本表示只包含大约15位有效数字。因此对于具有超过15位有效数字的几何图形,以下操作将导致损失:

SELECT ST_GeomFromText(ST_AsText(geom));

相反,以下操作不会导致损失

 SELECT ST_WKBFromText(ST_AsWKB(geom));

ST_GeoFromWKB示例

 SELECT ST_GeomFromWKB(
 E'\\001\\001\\000\\000\\000\\321\\256B\\312O
 \\304Q\\300\\347\\030\\220\\275\\336%E@',
 4326
 );

WKB表示形式将反斜杠用作内部分隔符。

ST_GEOMFROMGML, ST_GEOMFROMGEOJSON, ST_GEOMFROMKML, ST_GEOMFROMTWKB, ST_GEOMFROMGEOHASH

除了wkt和wkb函数外,还有其它格式 的输输入函数。

Geography Markup Language (GML)—ST_GeomFromGML

GeoJSON—ST_GeomFromGeoJSON

Keyhole Markup Format (KML)—ST_GeomFromKML

Tiny WKB—ST_GeomFromTWKB

GeoHash—ST_GeomFromGeoHash

使用文本和二进制格式创建地理图形

geography具有与geometry类似相似的函数,用于将各种格式的数据转换为地理图形;ST_GeogFromText, ST_GeogFromWKB, ST_GeogFromKML, ST_GeogFromGML, and ST_GeogFromGeoJSON。

与同类geometry函数相比,这些函数具有一些明显的局限性

它们不支持TIN、多面体表面或曲面几何图形等类型,因为geography本身不支持这些类型。

除非具体指定,否则这些函数将始终假定输入格式使用SRID 4326。

将文本或二进制表示用作函数参数

1. 类型歧义导致函数调用失败

PostgreSQL 需要明确知道参数类型才能正确调用函数。当函数存在重载(如同时支持geometrygeography)时,直接传入文本会导致类型歧义。

示例错误

SELECT ST_Perimeter('POLYGON((145.007 13.581,144.765 13.21,...))');
-- 错误:function ST_Perimeter(unknown) is not unique
  • 原因ST_Perimeter同时存在针对geometrygeography的实现,PostgreSQL 无法从文本推断应该使用哪种类型。

2. 隐式类型转换的不可靠性

虽然某些函数(如ST_Centroid)在当前版本中可能通过隐式转换正常工作,但这种行为依赖于:

  • 函数未被重载(仅支持geometry

  • PostgreSQL 的自动类型推断规则

示例(潜在风险)

SELECT ST_Centroid('LINESTRING(1 2,3 4)');  -- 当前版本可能正常工作
  • 风险:若未来 PostGIS 为ST_Centroid添加geography支持,此代码将因类型歧义而失效。

推荐实践

始终使用构造函数

SELECT ST_Area(ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))', 4326));

显式类型转换

SELECT ST_AsText('LINESTRING(1 2,3 4)'::geometry);

访问器和设置器函数

空间参考标识符

ST_SRID函数检索几何图形的SRID。地理地形的SRID通常为4326,因此地理图形中不存在ST_SRID函数。如果不使用默认的SRID,可能需要确定是假的SRID。通过将geography强制转换为geometry,可以获得SRID,如下所示:

SELECT ST_SRID(geog::geometry);

ST_SRID对应的设置器函数是ST_SetSRID。同样的,geography类型中不存在ST_SetSRID函数。这个设置函数将替换嵌入geometry中的空间参考元数据。

仅修改元数据ST_SetSRID不会转换坐标,仅修改 SRID 值

sql

-- 错误示例:错误设置SRID导致坐标系统与实际位置不匹配
SELECT ST_AsText(ST_SetSRID(ST_Point(-71, 42), 3857));
-- 结果:POINT(-71 42),但被错误标记为Web Mercator投影

正确转换坐标:使用ST_Transform

SELECT ST_AsText(ST_Transform(ST_SetSRID(ST_Point(-71, 42), 4326), 3857));
-- 结果:POINT(-7906117.8104 5087123.1217)(正确投影到Web Mercator)

所有几何图形都必须具有SRID,即使它的SRID是未知的。

用法:

 SELECT ST_SRID(ST_GeomFromText('POLYGON((1 1,2 2,2 0,1 1))',4326));  
SELECT ST_SRID(geom) As srid, COUNT(*)
FROM sometable
 GROUP BY ST_SRID(geom);
 Simple use 
of ST_SRID
 SELECT
 ST_SRID(geom) As srid,
 ST_SRID(ST_SetSRID(geom,4326)) as srid_new  
FROM (
 VALUES
 (ST_GeomFromText('POLYGON((70 20,71 21,71 19,70 20))',4269)),
 (ST_Point(1,2))
 ) As X (geom);

将几何图形转换为不同的空间参考

ST_Transform函数将给定geometry的所有点转换为另一个空间参考系统中的坐标。这个函数的常见应用是获取用经纬度表示的几何图形并将其转换为平面SRS,以便进行有意义的测量,或将非WGS 84类型的geometry类型转换为WGS 85,以便将其转换为geography类型。

 SELECT ST_AsEWKT(
 ST_Transform('SRID=4326;LINESTRING(-73 41,-72 42)'::geometry,32618)
 );

使用地理类型的转换

geography类型没有ST_Transform、ST_SetSRID或ST_SRID函数,因为这些类型几乎总是使用WGS 84 lon/lat。可以转换为geometry之后转换为回去

 SELECT
 ST_Transform(
 ST_ClosestPoint(
 ST_Transform(geog::geometry,32618),
 ST_Transform(
 'SRID=4326;LINESTRING(-73 41,-72 42)'::geometry,32618
 )
 ),
 4326
 )::geography
 FROM ( VALUES
 (
 'SRID=4326;LINESTRING(-73.5 41,-72.456 41.34)'::geography
 ),
 (
 'SRID=4326;POINT(-73.2 41.123)'::geography
 )
 )AS f(geog);

几何类型函数

GeometryType以大写形式返回熟悉的几何类型

新版本ST_GeometryType 输出几何类型的名称

 SELECT ST_GeometryType(geom) As new_name, GeometryType(geom) As old_name
 FROM (VALUES
 (ST_GeomFromText('POLYGON((0 0,1 1,0 1,0 0))')),
 (ST_Point(1,2)),
 (ST_MakeLine(ST_Point(1,2), ST_Point(1,2))),
 (ST_Collect(ST_Point(1,2), ST_Buffer(ST_Point(1,2),3))),
 (ST_LineToCurve(ST_Buffer(ST_Point(1,2),3))),
 (ST_LineToCurve(ST_Boundary(ST_Buffer(ST_Point(1,2),3)))),
 (ST_Multi(ST_LineToCurve(ST_Boundary(ST_Buffer(ST_Point(1,2),3)))))
 ) As x(geom);

使用SQL CASE语句针对异构geometry列有选择地应用函数的简练方法

SELECT
 CASE
 WHEN GeometryType(geom) = 'POLYGON' THEN ST_Area(geom)
 WHEN GeometryType(geom) = 'LINESTRING' THEN ST_Length(geom)
 ELSE NULL
 END As measure
 FROM sometable;

几何维度和坐标维度

几何维度——完全包含几何图形的最小维度空间

坐标维度——几何图形所在空间的维度

坐标维度始终大于或等于几何维度

ST_CoordDim 和 ST_Dimension分别用于返回坐标维度和几何维度

 SELECT
 ST_GeometryType(geom) As type,
 ST_Dimension(geom) As gdim,
 ST_CoordDim(geom) as cdim
 FROM unconstrained_geoms;

所有几何图形的坐标维度均为3,因为所有几何图形都有X Y Z坐标。只有多面体表面的几何维度为3,因为它是唯一真正的3D类型

检索坐标

ST_X, ST_Y, and ST_Z是用于返回几何点的基础坐标的函数。虽然地理类型中的点没有这个函数,但可以通过将地理类型点转换为几何点来使用这些函数。通常这些函数与ST_Centroid相结合,从而获取形状不是点的几何图形形心的X坐标和Y坐标

ST_Xmin, ST_Xmax, ST_Ymin, ST_Ymax, ST_Zmin, and ST_Zmax都是以边界框作为输入的函数,但也可以使用这些函数处理几何图形,因为PostGIS会在需要时将几何图形自动转换为其边界框。这些函数用于返回每个几何图形的最小或最大坐标。

检查几何有效性

用于检查有效性的函数是适用于几何图形,而不适用于地理图形。

ST_IsValid函数用于测试有效性,ST_IsValidReason简要说明了几何图形无效的原因。ST_IsValidReason将仅对遇到的第一个无效情形提供描述,因此如果几何图形因多种原因而无效,将只能看到第一个原因。如果几何图形有效,它将返回字符串“Valid Geometry”

ST_IsValidDetail是PostGIS2.0以后版本可用的函数。此函数返回一组valid_detail对象,每个对象包含特定无效的原因和位置,仅允许查看所有无效原因,而不仅仅是第一个。

ST_MakeValid函数,尝试修复无效的几何图形。

所有有效性检查仅检查X和Y,而不检查Z。它们会自动拒绝多面图表面和TIN

除非确认几何图形是有效的,负责不要尝试处理他们

定义几何图形的点数

ST_NPoints返回定义几何图形的点数。它不适用于地理图形,但可将geography类型强转为geometry类型,然后使用该函数。

ST_NumPoints仅在应用于线串时有效

在 PostGIS 2.0 版本之前,当ST_NumPoints函数用于多线串(multilinestrings) 时,存在异常行为

  • 该函数只会计算多线串中第一条线串(linestring) 的点数,而忽略其他线串。

  • 这一行为不符合预期(用户可能希望统计所有线串的总点数),且未在官方文档中明确说明,容易导致错误。

为解决上述问题并更好地遵循OGC(开放地理空间联盟)标准,PostGIS 2.0 及更高版本对这三个函数进行了调整:

  • 完全移除了对多线串的支持:如果向ST_NumPointsST_StartPointST_EndPoint传入多线串,或包含多线串的集合(如GEOMETRYCOLLECTION),函数会直接返回NULL

  • 目的是明确告知用户:这些函数不适合处理多线串,避免因隐含的错误逻辑(如只处理第一条线串)导致结果偏差。

测量函数

几何平面测量

测量函数ST_Length, ST_3DLength, ST_Area, ST_Perimeter, and ST_3DPerimeter

如果空间参考系统以经纬度为单位。那么在PostGIS将经纬度映射为XY坐标值之后,测量单位以度为单位。这只适合远离两级的小区域,在这些,经纬度在某种程序上任然是均匀地正方形。

从PostGIS2.0开始可以传入3D几何图形,但注意只测量几何图形的2D投影。要获得真正的3D测量值,必须使用新的函数: ST_3DClosestPoint, ST_3DDistance, ST_3DIntersects, ST_3DMaxDistance, or ST_3DPerimeter。

ST_3DLength

ST_3DIntersects, ST_3DDistance, ST_3DMaxDistance, and ST_3DClosestPoint也适用于多面体和TIN

 SELECT ST_Length(geom) As length_2d, ST_3DLength(geom) As length_3d
 FROM (
 VALUES
 (ST_GeomFromText('LINESTRING(1 2 3,4 5 6)')),
 (ST_GeomFromText('LINESTRING(1 2,4 5)')))
 As x(geom);

对于2D线串,两个函数返回值相同

多余3D线串,两个函数返回长度不等

对多边形集合 ST_Perimter计算所有环长度。

ST_Area和ST_Perminter只考虑X和Y坐标

如果要考虑Z坐标,要使用ST_3DArea和ST_3DPerminter

大地测量

地球是球体,大范围地理数据需用球面坐标系(大地测量学),而非平面笛卡尔坐标系,因球面会影响长度、面积等测量结果(如两点最短路径是球面曲线,两极间最短路径有无数条)。

  • 地理类型(geography):处理经纬度坐标(WGS 84,SRID 4326),考虑地球曲率,单位为米,直接计算大圆距离(如休斯顿到孟买约 14,456 公里),适合大范围区域。

  • 几何类型(geometry):基于笛卡尔坐标系,默认计算结果单位为度数(直接转换为公里会出错),但可通过球面函数(如 ST_LengthSpheroid)指定椭球体进行球面计算,结果与地理类型一致,且支持自定义椭球体(适用于其他天体)。

选择建议

  • 若处理大范围区域、仅需简单测量和关系检查,选 geography。

  • 若处理小范围区域(如城镇)、需复杂几何处理(如合并、简化),或依赖更多工具支持,选 geometry,因其函数更丰富、运算更快,且工具兼容性更广。

分解函数

几何图形的边界框

2D几何图形的边界框是box2D对象,他是完全包围几何图形的最小轴对齐二维框。

PostGIS还有一种box3D的长方体框,适用于处理3D对象,也是轴对齐的。

所有几何图形都有边界框,甚至点。

2D边界框的语法和文本表示为BOX(p1,p2),其中p1和p2是两个相对的顶点。

尽管可以认为地理图形具有边界框,但他们只是PostGIS用于空间关系查询的内部构造,而且没有物理变现。

 SELECT name, Box2D(geom) As box2d, Box3D(geom) As box3d
 FROM (VALUES
 ('2D Line',
 ST_GeomFromText(
 'LINESTRING(121.63 25.03,3.03 6.58,-71.06 42.36)',4326
 )
 ),
 ('3D Line', ST_GeomFromText('LINESTRING(1 2 3,3 4 1000.34567)')),
 ('Vert 2D Line', ST_GeomFromText('LINESTRING(1 2,1 4)')),
 ('Point', ST_GeomFromText('POINT(1 2)')),
 ('Polygon', ST_GeomFromText('POLYGON((1 2,3 4,5 6,1 2))')),
 ('Cube',
 ST_GeomFromText(
 'POLYHEDRALSURFACE(
 ((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),
 ((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),
 ((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),
 ((1 1 0,1 1 1,1 0 1,1 0 0,1 1 0)),
 ((0 1 0,0 1 1,1 1 1,1 1 0,0 1 0)),
 ((0 0 1,1 0 1,1 1 1,0 1 1,0 0 1))
 )'
 )
 )
 )
 AS x(name,geom);

生成边界和将多边形转换成线串

ST_Boundary适用于所有几何图形,但不适用于地理图形,它返回的几何图形决定了几何图形中的点与坐标空间的其他点之间的距离。几何图形的边界至少比几何图形本身低一个维度。

ST_Boundary用于以线串或线串的起止点的形式返回多边形和多边形集合的内环和外环。ST_Boundary同样适用于曲线几何图形,但它会在返回边界之前对曲线几何图形应用曲线到直线的操作。

 SELECT object_name,ST_AsText(ST_Boundary(geom)) As WKT
 FROM (VALUES
 ('Simple linestring',
 ST_GeomFromText('LINESTRING(-14 21,0 0,35 26)')
 ),
 ('Non-simple linestring',
 ST_GeomFromText('LINESTRING(2 0,0 0,1 1,1-1)')
 ),
 ('Closed linestring',
 ST_GeomFromText('
 LINESTRING(
 52 218,139 82,262 207,245 261,207 267,153 207,
 125 235,90 270,55 244,51 219,52 218)'
 )
 ),
 ('Polygon',
 ST_GeomFromText('
 POLYGON((
 52 218 1,139 82 1,262 207 1,245 261 1,207 267 1,153 207 1,
 125 235 1,90 270 1,55 244 1,51 219 1,52 218 1))'
 )
 ),
 ('Polygon with holes',
 ST_GeomFromText('
 POLYGON(
 (-0.25-1.25,-0.25 1.25,2.5 1.25,2.5-1.25,-0.25-1.25),
 (2.25 0,1.25 1,1.25-1,2.25 0),
 (1-1,1 1,0 0,1-1))'
 )
 ),
 ('Solid circle',
 ST_GeomFromText('CURVEPOLYGON(
 CIRCULARSTRING(0 0, 2 0, 2 2, 0 2, 0 0)
 )'))
 )
 AS x(object_name,geom);

ST_Boundary行为:

  • 简单或非简单的开放线串将返回一个由两个点组成的点的集合,其中的点为两个端点。

  • 闭合线串没有边界

  • 没有孔的多边形将返回外环的线串

  • 带孔的多边形返回线串集合,其中的线串是每个环返回的闭合线串。线串集合的第一个元素始终是外环

  • 多边形集合始终返回线串集合

ST_Boundary的一个更专业的对等函数是ST_ExteriorRing。此函数仅接受多边形并返回外环。不会返回内环

可以使用ST_InteriorRingN以获取单个内环或使用ST_DumpRings以获取外环和所有内环

形心、中间点和表面上的点

在PostGIS中,ST_Centroid和ST_PointOnSurface通常用于生成多边形的标记点。这两个函数仅适用于2D几何图形。虽然可将他们用于3D多边形,但Z和M坐标会被忽略。假设几何图形中的每个点都具有相等的质量,几何图形的形心可以被视为重心。唯一需要注意的是,形心可能不在几何图形内部。ST_Centroid不适用于曲线几何图形。

当求得的点并不在几何图形上时,ST_Centroid有时会产生不理想的视觉效果。在这种情况下,ST_PointOnSurface可以解决问题。它始终返回边界几何图形上的任意点。ST_PointOnSurface适用于除曲线外的所有2D几何图形。对于点,线串,点集合和线串集合,它考虑M和Z坐标,并返回一个通常用于定义几何图形的点。对于多边形,他将删去M和Z坐标。

ST_GeometricMedian是PostGIS 2.3中引入的一个用于点集合的函数。它在分析观察点时非常方便,返回位于所有点中间的点。中间点不像ST_Centroid那样容易受异常值的影响,因此在处理点集合时,ST_GeometricMedian比ST_Centroid更适用。

 SELECT
 name,
 ST_AsEWKT(ST_Centroid(geom)) As centroid,
 ST_AsEWKT(ST_PointOnSurface(geom)) As point_on_surface,
 CASE WHEN ST_GeometryType(geom) ILIKE '%Point%'
 THEN ST_AsEWKT(ST_GeometricMedian(geom))
 ELSE NULL END As geom_median
 FROM (VALUES
 ('Multipoint',ST_GeomFromText('MULTIPOINT(-1 1,0 0,2 3)')),
 ('Multipoint 3D',ST_GeomFromText('MULTIPOINT(-1 1 1,0 0 2,2 3 1)')),
 ('Multilinestring',
 ST_GeomFromText('MULTILINESTRING((0 0,0 1,1 1),(-1 1,-1-1))')
 ),
 ('Polygon',ST_GeomFromEWKT('
 POLYGON(
 (-0.25-1.25,-0.25 1.25,2.5 1.25,2.5-1.25,-0.25-1.25),
 (2.25 0,1.25 1,1.25-1,2.25 0),
 (1-1,1 1,0 0,1-1)
 )')
 )
 )
 As x(name,geom);

返回定义几何图形的点

1. ST_PointN函数

功能

专门用于从线串(Linestring)圆弧线串(Circularstring) 中提取指定位置的点。

特点

  • 仅适用于 1 维几何对象:线串(Linestring)和圆弧线串(Circularstring),不能用于多边形(Polygon)等其他类型。

  • 索引从1 开始(而非 0),即第一个点的索引是 1。

示例解析

SELECT ST_AsText(
  ST_PointN(ST_GeomFromText('LINESTRING(1 2,3 4,5 8)'), 2)
);
  • 步骤 1:ST_GeomFromText将 WKT 文本LINESTRING(1 2,3 4,5 8)转换为线串几何对象(包含 3 个点)。

  • 步骤 2:ST_PointN(geom, 2)提取该线串的第 2 个点。

  • 步骤 3:ST_AsText将提取的点转换为 WKT 格式,结果为POINT(3 4)

2. ST_DumpPoints函数

功能

用于从任意类型的几何对象中提取所有点,返回一个包含所有点的集合。

特点

  • 适用范围广:支持所有几何类型(线串、多边形、带孔多边形、复合几何等)。

  • 返回结果类型:geometry_dump对象的集合,每个对象包含两部分:

    • path:一维数组,表示点在原几何中的位置路径(用于标识点的归属和顺序)。

    • geom:点的几何对象(始终为POINT类型)。

用途

  • 解构复杂几何:将多边形、带孔多边形等复杂几何的所有顶点(包括外环、内环的点)提取出来。

  • 跨工具兼容:将 PostGIS 几何类型转换为点集合,方便导出到 R 等不直接支持 PostGIS 类型的工具中。

  • 拆分几何:例如将长线串拆分为多个短线段(需结合其他函数)。

示例场景

假设对一个多边形使用ST_DumpPoints

SELECT (ST_DumpPoints(geom)).* 
FROM (SELECT ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))') AS geom) AS t;
  • 结果会返回多边形外环的 5 个顶点(包括闭合的起点 / 终点)。

  • 每个点的path数组为{1,1,n}1表示外环,n表示点在环中的顺序)。

分解多个几何图形和几何图形集合

ST_GeometryN and ST_Dump都用于将多个几何图形和几何图形集合分解为其组件几何图形,但他们并不总是返回相同的答案。ST_Dump递归转储所有包含的几何图形,而ST_GeometryN仅获取一种几何图形。ST_Dump和ST_DumpPoints相似,返回一组geometry_dump对象。返回的几何图形将始终是单一几何图形,而不是几何图形集合。

两者的区别与适用场景

特性

ST_GeometryN

ST_Dump

返回结果

单个子几何(如LINESTRING

包含pathgeomgeometry_dump集合

用途

提取指定位置的子几何

批量拆分所有子几何

索引依赖

需要显式指定索引n

无需指定索引,返回所有子几何

适用场景

已知子几何位置,需精准提取

需遍历所有子几何(如批量处理、分析)

对带孔多边形的支持

不支持(无法拆分内环)

支持(拆分外环和所有内环)

合成函数

合成点

点时最基本的几何图形。可以通过原始坐标创建点的函数由两个:ST_Point和ST_MakePoint。

ST_Point仅适用于2D坐标。ST_MakePoint和ST_MakePointM可以接受2D之外的带M值的2D 3D和4D坐标,但这两个函数是PostGIS特有的。以上三个函数具有相同的语法:只有一个由逗号分隔的坐标参数。因为这些参数不以SRID作为参数,所以他们需要与ST_SetSRID一起使用以包含SRID信息。

合成多边形

1. ST_MakeEnvelope

功能

快速创建一个轴对齐的矩形多边形(边界框,Bounding Box),适用于生成规则的矩形区域。

语法

ST_MakeEnvelope(minx, miny, maxx, maxy, [srid])
  • 参数:

    • minx, miny:矩形左下角坐标

    • maxx, maxy:矩形右上角坐标

    • srid(可选):空间参考系 ID,如 4326(WGS84 经纬度)

特点

  • 生成的多边形始终是矩形,边与 X 轴、Y 轴平行

  • 内部无孔洞,是最简单的多边形创建方式

  • 效率高,适合快速生成边界范围

示例

-- 创建一个经纬度范围的矩形(北京大致范围)
SELECT ST_AsText(
  ST_MakeEnvelope(115.4, 39.4, 117.5, 41.0, 4326)
);
-- 结果:POLYGON((115.4 39.4, 117.5 39.4, 117.5 41, 115.4 41, 115.4 39.4))

2. ST_MakePolygon

功能

通过闭合线串(LinearRing) 创建多边形,支持添加内部孔洞。

语法

-- 基本用法(无孔洞)
ST_MakePolygon(outer_ring)

-- 带孔洞(外环+多个内环)
ST_MakePolygon(outer_ring, inner_rings_array)
  • 参数:

    • outer_ring:必须是闭合的线串(LINESTRING),且起点与终点必须重合

    • inner_rings_array(可选):由闭合线串组成的数组,表示内部孔洞

特点

  • 灵活性高,可创建任意形状的多边形(不仅限于矩形)

  • 要求输入的线串必须闭合且简单(不自相交)

  • 支持创建带孔洞的复杂多边形

示例

-- 创建一个三角形多边形(无孔洞)
SELECT ST_AsText(
  ST_MakePolygon(
    ST_GeomFromText('LINESTRING(0 0, 1 0, 0.5 1, 0 0)')  -- 闭合线串
  )
);
-- 结果:POLYGON((0 0, 1 0, 0.5 1, 0 0))

-- 创建带孔洞的多边形
SELECT ST_AsText(
  ST_MakePolygon(
    ST_GeomFromText('LINESTRING(0 0, 10 0, 10 10, 0 10, 0 0)'),  -- 外环
    ARRAY[
      ST_GeomFromText('LINESTRING(2 2, 8 2, 8 8, 2 8, 2 2)')     -- 内环(孔洞)
    ]::geometry[]
  )
);

3. ST_BuildArea

功能

通过闭合的线串集合创建多边形,自动将闭合区域转换为多边形。

语法

ST_BuildArea(geom)
  • 参数:geom 可以是单个闭合线串、MULTILINESTRINGGEOMETRYCOLLECTION(包含闭合线串)

特点

  • 自动识别闭合区域:只要线串形成闭合环,无论是否显式声明为多边形边界

  • 支持多个闭合环:若输入多个不相交的闭合线串,返回 MULTIPOLYGON

  • 常用于将 CAD 或矢量数据中的闭合线条转换为面要素

示例

-- 将闭合线串转换为多边形
SELECT ST_AsText(
  ST_BuildArea(
    ST_GeomFromText('LINESTRING(0 0, 1 0, 1 1, 0 1, 0 0)')
  )
);
-- 结果:POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))

-- 将多个闭合线串转换为多多边形
SELECT ST_AsText(
  ST_BuildArea(
    ST_GeomFromText('MULTILINESTRING(
      (0 0, 2 0, 2 2, 0 2, 0 0),
      (5 5, 7 5, 7 7, 5 7, 5 5)
    )')
  )
);
-- 结果:MULTIPOLYGON(((0 0, 2 0, 2 2, 0 2, 0 0)), ((5 5, 7 5, 7 7, 5 7, 5 5)))

4. ST_Polygonize

功能

相互连接的线串网络转换为多边形集合,自动识别线串围成的闭合区域。

语法

ST_Polygonize(geomset)
  • 参数:geomset 是线串的集合(MULTILINESTRING 或线串组成的表)

特点

  • 处理复杂线网:适合将道路网、水系网等交叉线串形成的闭合区域转换为多边形

  • 自动处理交叉关系:即使线串未完全闭合(但整体形成闭合区域)也能识别

  • 返回 GEOMETRYCOLLECTIONMULTIPOLYGON,包含所有识别出的多边形

示例

-- 将交叉线串网络转换为多边形
SELECT ST_AsText(
  ST_Polygonize(
    ST_GeomFromText('MULTILINESTRING(
      (0 0, 0 2, 2 2, 2 0, 0 0),  -- 外框
      (0 1, 2 1),                -- 水平线
      (1 0, 1 2)                 -- 垂直线
    )')
  )
);
-- 结果:GEOMETRYCOLLECTION(
--   POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)),
--   POLYGON((1 0, 1 1, 2 1, 2 0, 1 0)),
--   ... (共4个小多边形)
-- )

将单个几何图形提升为几何图形集合

ST_Multi函数通常在PostGIS中使用,主要用于将点、线串和多边形提升为对应的集合,即使他们只有一个几何图形。如果PostGIS已经是集合,它将保持不变

ST_Multi的主要用例是确保表列中的所有几何图形都具有相同的类型,以确保一致性。

简化函数

1. ST_SnapToGrid

功能

将几何对象的所有坐标 “捕捉” 到指定的规则网格上,通过统一坐标精度来减少数据量或消除微小误差。

语法

sql

ST_SnapToGrid(geom, origin_x, origin_y, size_x, size_y)  -- 完整参数(指定网格原点和大小)
ST_SnapToGrid(geom, size)  -- 简化参数(网格原点为(0,0),x/y方向网格大小相同)
  • 参数:

    • geom:输入几何对象(点、线、面等)。

    • origin_x, origin_y:网格的原点坐标(可选,默认 (0,0))。

    • size_x, size_y:x/y 方向的网格单元大小(核心参数,决定精度)。

    • size:简化写法,x/y 方向网格大小均为size

原理

坐标会被 “吸附” 到最近的网格点上。例如,若网格大小为0.5,则坐标(1.23, 2.78)会被调整为(1.0, 2.5)(距离最近的网格点)。

示例

-- 将点坐标捕捉到0.5x0.5的网格上
SELECT ST_AsText(
  ST_SnapToGrid(ST_GeomFromText('POINT(1.23 2.78)'), 0.5)
);
-- 结果:POINT(1.0 2.5)

-- 对线串应用网格捕捉(原点(0,0),x方向0.1,y方向0.2)
SELECT ST_AsText(
  ST_SnapToGrid(
    ST_GeomFromText('LINESTRING(1.123 2.456, 3.789 4.012)'),
    0, 0, 0.1, 0.2
  )
);
-- 结果:LINESTRING(1.1 2.4, 3.8 4.0) (x保留到0.1,y保留到0.2)

特点与适用场景

  • 核心作用:统一坐标精度,消除因测量误差导致的微小坐标差异(如1.00000010.9999999可被统一为1.0)。

  • 优点:操作简单,可灵活控制 x/y 方向的精度。

  • 缺点:网格大小需手动指定,若设置不当可能过度简化(丢失重要细节)。

  • 适用场景:数据清洗(去除冗余小数)、降低存储成本、地图匹配(将点吸附到道路网格)。

2. ST_QuantizeCoordinates

功能

通过限制坐标的小数位数(或有效数字)来量化坐标,本质是 “四舍五入” 坐标值到指定精度,比ST_SnapToGrid更直观控制小数位数。

语法

ST_QuantizeCoordinates(geom, digits)
  • 参数:

    • geom:输入几何对象。

    • digits:保留的小数位数(整数,可正可负)。例如:

      • digits=2:保留 2 位小数(如1.2341.23)。

      • digits=-1:保留到十位(如123120)。

原理

直接对坐标值进行四舍五入,保留指定的小数位数,而非 “网格吸附”。例如,digits=1时,(1.23, 4.56)(1.2, 4.6)

示例

-- 保留1位小数
SELECT ST_AsText(
  ST_QuantizeCoordinates(ST_GeomFromText('POINT(1.234 5.678)'), 1)
);
-- 结果:POINT(1.2 5.7)

-- 保留到百位(digits=-2)
SELECT ST_AsText(
  ST_QuantizeCoordinates(ST_GeomFromText('POINT(1234 5678)'), -2)
);
-- 结果:POINT(1200 5700)

特点与适用场景

  • 核心作用:精确控制坐标的小数位数,适合需要明确精度的场景(如要求坐标保留 2 位小数)。

  • 优点:参数直观(直接指定小数位数),比ST_SnapToGrid更易理解。

  • 缺点:x/y 方向精度绑定(无法分别控制 x 和 y 的小数位数)。

  • 适用场景:数据标准化(统一坐标精度)、满足特定格式要求(如某些系统只接受 3 位小数坐标)。

3. ST_Simplify

功能

使用道格拉斯 - 普克(Douglas-Peucker)算法简化几何对象,通过移除 “不重要” 的顶点来减少几何复杂度(顶点数量)。

语法

ST_Simplify(geom, tolerance)

参数:

  • geom:输入几何(线串、多边形等,点无意义)。

  • tolerance:距离容差(正数,单位与几何坐标一致)。容差越大,简化越彻底(保留的顶点越少)。

原理

算法通过迭代判断顶点是否在 “简化路径” 的容差范围内:若顶点到线段的距离小于容差,则被移除;否则保留。例如,一条包含 100 个顶点的曲线,用tolerance=10简化后可能只剩 10 个关键顶点。

示例

-- 简化线串(容差0.5)
SELECT ST_NPoints(  -- 计算顶点数量
  ST_Simplify(
    ST_GeomFromText('LINESTRING(0 0, 0.1 0.2, 0.3 0.1, 0.5 0.4, 1 0)'),
    0.5
  )
);
-- 原顶点数:5 → 简化后可能为2(仅保留起点和终点,中间点距离容差内)

特点与适用场景

  • 核心作用:减少几何顶点数量,降低数据复杂度(如曲线变折线)。

  • 优点:简化效率高,适合快速处理大量数据。

  • 缺点:可能破坏拓扑关系(如简化后多边形自相交、线串交叉)。

  • 适用场景:低精度可视化(如小比例尺地图)、提升空间索引效率(顶点少的几何查询更快)。

4. ST_SimplifyPreserveTopology

功能

在简化几何的同时保持拓扑关系(如避免多边形自相交、确保邻接多边形不重叠 / 分离),是ST_Simplify的 “安全版”。

语法

ST_SimplifyPreserveTopology(geom, tolerance)
  • 参数与ST_Simplify一致:geom为输入几何,tolerance为距离容差。

原理

基于Visvalingam-Whyatt 算法(或改进的道格拉斯 - 普克算法),在简化过程中加入拓扑检查,确保简化后的几何不出现自相交、重叠等拓扑错误。例如,相邻的两个多边形简化后仍保持边界一致,不出现缝隙或重叠。

示例

-- 简化多边形(保持拓扑,避免自相交)
SELECT ST_IsValid(  -- 检查几何是否有效(无自相交)
  ST_SimplifyPreserveTopology(
    ST_GeomFromText('POLYGON((0 0, 0.1 0.2, ... , 0 0))'),  -- 复杂多边形
    0.5
  )
);
-- 结果:t(true),即使容差较大,仍保持多边形有效

特点与适用场景

  • 核心作用:在简化几何的同时保证拓扑正确性,适合对拓扑关系敏感的场景。

  • 优点:避免自相交、重叠等错误,确保几何 “合法性”。

  • 缺点:计算成本高于ST_Simplify(需额外拓扑检查)。

  • 适用场景:高精度地图简化(如行政区划边界)、拓扑分析(如网络分析、邻接关系计算)。

5. ST_ReducePrecision

功能

通过降低坐标的有效精度来减少数据量,与ST_QuantizeCoordinates类似,但精度控制方式更灵活(基于 “有效位数” 而非小数位数)。

语法

ST_ReducePrecision(geom, precision)
  • 参数:

    • geom:输入几何对象。

    • precision:精度参数(正数,代表 “有效位数” 的近似控制)。例如,precision=1e6表示坐标值保留到百万分之一级(约 6 位小数)。

原理

通过截断坐标的二进制表示来降低精度,本质是减少坐标的存储位数(如从 64 位浮点数降为 32 位),效果类似 “保留指定有效位数”。

示例

-- 降低点坐标精度(precision=1000,约保留3位小数)
SELECT ST_AsText(
  ST_ReducePrecision(ST_GeomFromText('POINT(123.456789 987.654321)'), 1000)
);
-- 结果:POINT(123.457 987.654) (近似保留3位小数)

特点与适用场景

  • 核心作用:通过降低坐标存储精度来优化性能(如减少内存占用、加快索引构建)。

  • 优点:更贴近计算机存储原理(基于二进制截断),效率较高。

  • 缺点:精度参数(precision)不如 “小数位数” 直观,需根据需求换算。

  • 适用场景:大规模空间数据存储优化、提升空间操作(如叠加分析)效率。