9. 几何图形

9.1. 简介

在之前的 部分 中,我们加载了各种数据。在我们开始玩弄数据之前,让我们看看一些更简单的例子。在 pgAdmin 中,再次选择 nyc 数据库并打开 SQL 查询工具。将此示例 SQL 代码粘贴到 pgAdmin SQL 编辑器窗口中(删除默认情况下可能存在的任何文本),然后执行。

CREATE TABLE geometries (name varchar, geom geometry);

INSERT INTO geometries VALUES
  ('Point', 'POINT(0 0)'),
  ('Linestring', 'LINESTRING(0 0, 1 1, 2 1, 2 2)'),
  ('Polygon', 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
  ('PolygonWithHole', 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))'),
  ('Collection', 'GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))');

SELECT name, ST_AsText(geom) FROM geometries;
_images/start01.png

上面的示例创建了一个表(geometries),然后插入了五个几何图形:一个点、一条线、一个多边形、一个带孔的多边形和一个集合。最后,插入的行被选择并显示在输出窗格中。

9.2. 元数据表

为了符合 SQL 简单要素规范 (SFSQL),PostGIS 提供了两个表来跟踪和报告给定数据库中可用的几何类型。

  • 第一个表,spatial_ref_sys,定义了数据库已知的所有空间参考系统,我们将在后面详细介绍。

  • 第二个表(实际上是一个视图),geometry_columns,提供了所有“要素”(定义为具有几何属性的对象)的列表,以及这些要素的基本详细信息。

_images/table01.png

让我们看看我们数据库中的 geometry_columns 表。像以前一样将此命令粘贴到查询工具中

SELECT * FROM geometry_columns;
_images/start08.png
  • f_table_catalogf_table_schemaf_table_name 提供包含给定几何图形的要素表的完全限定名称。由于 PostgreSQL 不使用目录,因此 f_table_catalog 通常为空。

  • f_geometry_column 是包含几何图形的列的名称 - 对于具有多个几何图形列的要素表,每个列都将有一条记录。

  • coord_dimensionsrid 分别定义几何图形的维度(二维、三维或四维)以及引用 spatial_ref_sys 表的空间参考系统标识符。

  • type 列定义了如下所述的几何类型;到目前为止,我们已经看到了点和线串类型。

通过查询此表,GIS 客户端和库可以确定检索数据时会遇到什么,并且可以执行任何必要的投影、处理或渲染,而无需检查每个几何图形。

注意

你的 nyc 表中是否有一些或所有表没有 srid 为 26918?通过更新表很容易解决。

ALTER TABLE nyc_neighborhoods
  ALTER COLUMN geom
  TYPE Geometry(MultiPolygon, 26918)
  USING ST_SetSRID(geom, 26918);

9.3. 表示现实世界中的对象

SQL 的简单要素 (SFSQL) 规范,PostGIS 开发的最初指导标准,定义了现实世界中对象的表示方式。通过对连续形状进行固定分辨率的数字化,我们可以获得对象的合理表示。SFSQL 仅处理二维表示。PostGIS 已将此扩展到包括三维和四维表示;最近,SQL-Multimedia 第 3 部分 (SQL/MM) 规范已正式定义了自己的表示方式。

我们的示例表包含不同几何类型的混合。我们可以使用读取几何元数据的函数收集有关每个对象的常规信息。

  • ST_GeometryType(geometry) 返回几何类型

  • ST_NDims(geometry) 返回几何的维数

  • ST_SRID(geometry) 返回几何的空间参考标识符号

SELECT name, ST_GeometryType(geom), ST_NDims(geom), ST_SRID(geom)
  FROM geometries;
      name       |    st_geometrytype    | st_ndims | st_srid
-----------------+-----------------------+----------+---------
 Point           | ST_Point              |        2 |       0
 Polygon         | ST_Polygon            |        2 |       0
 PolygonWithHole | ST_Polygon            |        2 |       0
 Collection      | ST_GeometryCollection |        2 |       0
 Linestring      | ST_LineString         |        2 |       0

9.3.1.

_images/points.png

空间表示地球上的单个位置。该点由单个坐标表示(包括二维、三维或四维)。当目标比例尺下形状和大小等精确细节不重要时,点用于表示对象。例如,世界地图上的城市可以描述为点,而单个州的地图可以将城市表示为多边形。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Point';
POINT(0 0)

一些用于处理点的特定空间函数是

  • ST_X(geometry) 返回 X 坐标

  • ST_Y(geometry) 返回 Y 坐标

因此,我们可以像这样从点读取坐标

SELECT ST_X(geom), ST_Y(geom)
  FROM geometries
  WHERE name = 'Point';

纽约市地铁站 (nyc_subway_stations) 表是一个表示为点的 dataset。以下 SQL 查询将返回与一个点关联的几何图形(在 ST_AsText 列中)。

SELECT name, ST_AsText(geom)
  FROM nyc_subway_stations
  LIMIT 1;

9.3.2. 线串

_images/lines.png

线串是位置之间的路径。它采用两个或多个点的有序序列的形式。道路和河流通常表示为线串。如果线串的起点和终点位于同一点,则称其为闭合。如果线串不交叉或不与自身接触(除非在闭合时在端点处),则称其为简单。线串可以同时是闭合简单的。

纽约的街道网络 (nyc_streets) 在研讨会中已加载。此 dataset 包含名称和类型等详细信息。一条现实世界中的街道可能包含许多线串,每个线串代表具有不同属性的路段。

以下 SQL 查询将返回与一条线串相关的几何图形(在 ST_AsText 列中)。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name = 'Linestring';
LINESTRING(0 0, 1 1, 2 1, 2 2)

一些用于处理线串的特定空间函数是

  • ST_Length(geometry) 返回线串的长度

  • ST_StartPoint(geometry) 返回第一个坐标作为点

  • ST_EndPoint(geometry) 返回最后一个坐标作为点

  • ST_NPoints(geometry) 返回线串中的坐标数量

因此,我们线串的长度是

SELECT ST_Length(geom)
  FROM geometries
  WHERE name = 'Linestring';
3.41421356237309

9.3.3. 多边形

_images/polygons.png

多边形是区域的表示。多边形的外部边界由环表示。该环是一条线串,如上所述,它既是闭合的又是简单的。多边形内的孔也由环表示。

多边形用于表示大小和形状都很重要的对象。当比例尺足够高以看到它们的面积时,城市界限、公园、建筑占地面积或水体通常都以多边形表示。道路和河流有时也可以用多边形表示。

以下 SQL 查询将返回与一个多边形相关的几何图形(在 ST_AsText 列中)。

SELECT ST_AsText(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';

注意

我们没有在 WHERE 子句中使用 = 符号,而是使用 LIKE 运算符执行字符串匹配操作。您可能习惯使用 ``*`` 符号作为模式匹配的“通配符”,但在 SQL 中,``%`` 符号与 LIKE 运算符一起使用,以告诉系统执行通配符匹配。

POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))
POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))

第一个多边形只有一个环。第二个多边形有一个内部“孔”。大多数图形系统都包含“多边形”的概念,但 GIS 系统在允许多边形明确地具有孔方面是比较独特的。

_images/polygons1.png

一些用于处理多边形的特定空间函数是

  • ST_Area(geometry) 返回多边形的面积

  • ST_NRings(geometry) 返回环的数量(通常为 1,如果存在孔则更多)

  • ST_ExteriorRing(geometry) 返回外环作为线字符串

  • ST_InteriorRingN(geometry,n) 返回指定的内环作为线字符串

  • ST_Perimeter(geometry) 返回所有环的长度

我们可以使用面积函数计算多边形的面积

SELECT name, ST_Area(geom)
  FROM geometries
  WHERE name LIKE 'Polygon%';
Polygon            1
PolygonWithHole    99

请注意,带孔的多边形的面积是外壳面积(10x10 平方)减去孔面积(1x1 平方)。

9.3.4. 集合

有四种集合类型,它们将多个简单几何图形分组为集合。

  • MultiPoint,点集合

  • MultiLineString,线字符串集合

  • MultiPolygon,多边形集合

  • GeometryCollection,任何几何图形(包括其他集合)的异构集合

集合是另一个概念,它在 GIS 软件中比在通用图形软件中出现得更多。它们对于直接将现实世界中的对象建模为空间对象很有用。例如,如何对被通行权分割的地块进行建模?作为MultiPolygon,在通行权的两侧各有一部分。

_images/collection2.png

我们的示例集合包含一个多边形和一个点

SELECT name, ST_AsText(geom)
  FROM geometries
  WHERE name = 'Collection';
GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))
_images/collection.png

用于处理集合的一些特定空间函数是

  • ST_NumGeometries(geometry) 返回集合中部件的数量

  • ST_GeometryN(geometry,n) 返回指定的部件

  • ST_Area(geometry) 返回所有多边形部件的总面积

  • ST_Length(geometry) 返回所有线性部件的总长度

9.4. 几何图形输入和输出

在数据库中,几何图形存储在磁盘上,使用的是仅由 PostGIS 程序使用的格式。为了让外部程序插入和检索有用的几何图形,需要将它们转换为其他应用程序可以理解的格式。幸运的是,PostGIS 支持以多种格式发出和使用几何图形

  • 众所周知的文本 (WKT)

    • ST_GeomFromText(text, srid) 返回 geometry

    • ST_AsText(geometry) 返回 text

    • ST_AsEWKT(geometry) 返回 text

  • Well-known binary (WKB)

    • ST_GeomFromWKB(bytea) 返回 geometry

    • ST_AsBinary(geometry) 返回 bytea

    • ST_AsEWKB(geometry) 返回 bytea

  • Geographic Mark-up Language (GML)

    • ST_GeomFromGML(text) 返回 geometry

    • ST_AsGML(geometry) 返回 text

  • Keyhole Mark-up Language (KML)

    • ST_GeomFromKML(text) 返回 geometry

    • ST_AsKML(geometry) 返回 text

  • GeoJSON

    • ST_AsGeoJSON(geometry) 返回 text

  • Scalable Vector Graphics (SVG)

    • ST_AsSVG(geometry) 返回 text

构造函数最常见的用途是将几何图形的文本表示形式转换为内部表示形式

请注意,除了具有几何图形表示形式的文本参数外,我们还有一个数字参数,用于提供几何图形的 SRID

以下 SQL 查询显示了 WKB 表示形式的示例(调用 encode() 是将二进制输出转换为 ASCII 形式以进行打印所必需的)

SELECT encode(
  ST_AsBinary(ST_GeometryFromText('LINESTRING(0 0,1 0)')),
  'hex');
01020000000200000000000000000000000000000000000000000000000000f03f0000000000000000

为了本研讨会的目的,我们将继续使用 WKT 以确保您可以阅读和理解我们正在查看的几何图形。但是,大多数实际过程,例如在 GIS 应用程序中查看数据、将数据传输到 Web 服务或远程处理数据,WKB 是首选格式。

由于 WKT 和 WKB 是在 SFSQL 规范中定义的,它们不处理 3 维或 4 维几何。对于这些情况,PostGIS 定义了扩展的 Well Known Text (EWKT) 和扩展的 Well Known Binary (EWKB) 格式。它们提供了与 WKT 和 WKB 相同的格式化功能,并增加了维度。

以下是一个 3D 线段的 WKT 示例

SELECT ST_AsText(ST_GeometryFromText('LINESTRING(0 0 0,1 0 0,1 1 2)'));
LINESTRING Z (0 0 0,1 0 0,1 1 2)

请注意文本表示发生了变化!这是因为 PostGIS 的文本输入例程对它所消耗的内容很宽松。它将消耗

  • 十六进制编码的 EWKB,

  • 扩展的 Well Known Text,以及

  • ISO 标准的 Well Known Text。

在输出方面,ST_AsText 函数是保守的,并且只发出 ISO 标准的 Well Known Text。

除了 ST_GeometryFromText 函数之外,还有许多其他方法可以从 Well Known Text 或类似格式的输入创建几何。

-- Using ST_GeomFromText with the SRID parameter
SELECT ST_GeomFromText('POINT(2 2)',4326);

-- Using ST_GeomFromText without the SRID parameter
SELECT ST_SetSRID(ST_GeomFromText('POINT(2 2)'),4326);

-- Using a ST_Make* function
SELECT ST_SetSRID(ST_MakePoint(2, 2), 4326);

-- Using PostgreSQL casting syntax and ISO WKT
SELECT ST_SetSRID('POINT(2 2)'::geometry, 4326);

-- Using PostgreSQL casting syntax and extended WKT
SELECT 'SRID=4326;POINT(2 2)'::geometry;

除了针对各种形式(WKT、WKB、GML、KML、JSON、SVG)的发射器之外,PostGIS 还为四种形式(WKT、WKB、GML、KML)提供了消费者。大多数应用程序使用 WKT 或 WKB 几何创建函数,但其他函数也适用。以下是一个使用 GML 作为输入并输出 JSON 的示例

SELECT ST_AsGeoJSON(ST_GeomFromGML('<gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point>'));
_images/represent-07.png

9.5. 从文本转换

我们迄今为止看到的 WKT 字符串都是“text”类型的,我们一直使用 PostGIS 函数(如 ST_GeomFromText())将它们转换为“geometry”类型。

PostgreSQL 包含一种简短的语法,允许将数据从一种类型转换为另一种类型,即转换语法,oldata::newtype。例如,以下 SQL 将双精度数转换为文本字符串。

SELECT 0.9::text;

更重要的是,以下 SQL 将 WKT 字符串转换为几何

SELECT 'POINT(0 0)'::geometry;

关于使用转换创建几何需要注意的一点是:除非指定 SRID,否则将获得一个 SRID 未知的几何。可以使用“扩展”的 Well Known Text 形式指定 SRID,该形式在前面包含一个 SRID 块

SELECT 'SRID=4326;POINT(0 0)'::geometry;

在使用 WKT 以及 geometrygeography 列(参见 Geography)时,使用转换符号非常常见。

9.6. 函数列表

ST_Area: 如果它是多边形或多边形,则返回表面的面积。对于“geometry”类型,面积以 SRID 单位表示。对于“geography”类型,面积以平方米表示。

ST_AsText: 返回几何/地理的 Well-Known Text (WKT) 表示,不包含 SRID 元数据。

ST_AsBinary: 返回几何/地理的 Well-Known Binary (WKB) 表示,不包含 SRID 元数据。

ST_EndPoint: 返回 LINESTRING 几何的最后一个点,作为 POINT。

ST_AsEWKB: 返回几何的 Well-Known Binary (WKB) 表示,包含 SRID 元数据。

ST_AsEWKT: 返回几何的 Well-Known Text (WKT) 表示,包含 SRID 元数据。

ST_AsGeoJSON: 返回几何作为 GeoJSON 元素。

ST_AsGML: 返回几何作为 GML 版本 2 或 3 元素。

ST_AsKML: 返回几何作为 KML 元素。有多种变体。默认版本=2,默认精度=15。

ST_AsSVG: 返回给定几何或地理对象的 SVG 路径数据中的几何。

ST_ExteriorRing: 返回表示 POLYGON 几何外部环的线字符串。如果几何不是多边形,则返回 NULL。不适用于 MULTIPOLYGON

ST_GeometryN: 如果几何是 GEOMETRYCOLLECTION、MULTIPOINT、MULTILINESTRING、MULTICURVE 或 MULTIPOLYGON,则返回第 N 个(从 1 开始)几何。否则,返回 NULL。

ST_GeomFromGML: 以几何的 GML 表示作为输入,并输出 PostGIS 几何对象。

ST_GeomFromKML: 以几何的 KML 表示作为输入,并输出 PostGIS 几何对象

ST_GeomFromText: 从 Well-Known Text 表示 (WKT) 返回指定的 ST_Geometry 值。

ST_GeomFromWKB: 从 Well-Known Binary 几何表示 (WKB) 和可选 SRID 创建几何实例。

ST_GeometryType: 返回 ST_Geometry 值的几何类型。

ST_InteriorRingN: 返回多边形几何的第 N 个内部线字符串环。如果几何不是多边形或给定的 N 超出范围,则返回 NULL。

ST_Length: 如果几何体是线字符串或多线字符串,则返回几何体的二维长度。几何体以空间参考的单位为单位,地理体以米为单位(默认球体)。

ST_NDims: 返回几何体的坐标维数,作为一个小整数。值是:2、3 或 4。

ST_NPoints: 返回几何体中的点数(顶点)。

ST_NRings: 如果几何体是多边形或多边形,则返回环数。

ST_NumGeometries: 如果几何体是 GEOMETRYCOLLECTION(或 MULTI*),则返回几何体的数量,否则返回 NULL。

ST_Perimeter: 返回 ST_Surface 或 ST_MultiSurface 值边界的长度测量值。(多边形、多边形)

ST_SRID: 返回 ST_Geometry 的空间参考标识符,如 spatial_ref_sys 表中定义。

ST_StartPoint: 返回 LINESTRING 几何体的第一个点,作为 POINT。

ST_X: 返回点的 X 坐标,如果不可用则返回 NULL。输入必须是点。

ST_Y: 返回点的 Y 坐标,如果不可用则返回 NULL。输入必须是点。