9. 几何(Geometries)

9.1. 介绍

前一节,我们加载了一些数据。在操作数据之前,我们先看一些更简单的例子。在 pgAdmin 中,再次选中 nyc 数据库,打开 SQL 查询工具。粘贴下列的 SQL 代码到 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

上面的示例 SQL 代码创建了一个名为 geometries 的数据表,插入了 5 个几何对象:1 点,1 线,1 多边形,1 带洞多边形,1 集合。最后,使用 SELECT 语句把插入的数据选出来并输出到面板上。

9.2. 元数据表

根据Simple Features for SQL (SFSQL)规范,PostGIS提供了两个表来跟踪和报告给定数据库中可用的几何类型。

  • 第一个表是``spatial_ref_sys``,它定义了数据库中已知的所有空间参考系统,并将在后面更详细地描述。

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

_images/table01.png

让我们来查看我们数据库中的``geometry_columns``表。像之前一样将这个命令粘贴到查询工具中:

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

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

  • ``coord_dimension``和``srid``分别定义了几何图形的维度(2、3或4维)和引用``spatial_ref_sys``表的空间参考系统标识符。

  • ``type``列定义了下面描述的几何类型;到目前为止,我们已经看到了Point和Linestring类型。

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

注解

你的``nyc``表中的一部分或全部是否没有``srid``为26918?通过更新表格可以轻松解决这个问题。

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

9.3. 表示真实世界的对象

Simple Features for SQL (SFSQL) 规范,是 PostGIS 开发的原始指导标准,定义了如何表示现实世界的对象。通过以固定分辨率对连续形状进行数字化,我们可以获得对象的可通过的表示。SFSQL 只处理二维表示。PostGIS 已将其扩展到包括三维和四维表示;最近 SQL-Multimedia Part 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

空间**点**表示地球上的一个位置。这个点由一个坐标表示(包括2、3或4个维度)。当在目标比例尺下,确切的细节,例如形状和大小,不重要时,通常使用点来表示对象。例如,在世界地图上,城市可以表示为点,而在单个州的地图上,城市可以表示为多边形。

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)表是一个以点表示的数据集。以下SQL查询将返回与一个点相关联的几何图形(在:command:`ST_AsText`列中)。

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

9.3.2. 线串

_images/lines.png

Linestring**是两个或多个位置之间的路径。它采用两个或多个点的有序系列的形式。道路和河流通常被表示为linestrings。如果Linestring从同一点开始和结束,则称其为**closed。如果Linestring不穿过或触及自身(如果它是封闭的,则除了在其端点处),则称其为**simple**。Linestring可以同时是**closed**和**simple**。

纽约市的街道网络(nyc_streets)在此前的研讨会中已加载。此数据集包含诸如名称和类型之类的详细信息。一个真实世界的街道可能由许多Linestring组成,每个Linestring表示具有不同属性的道路段。

以下SQL查询将返回与一个Linestring相关联的几何图形(在:command:`ST_AsText`列中)。

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

一些用于处理Linestring的特定空间函数包括:

  • ST_Length(geometry) 返回Linestring的长度

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

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

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

因此,我们Linestring的长度是:

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

9.3.3. 多边形

_images/polygons.png

多边形是一个区域的表示。多边形的外边界由一个环表示。这个环是一个根据上面定义的封闭和简单的Linestring。多边形内的孔也由环表示。

多边形用于表示尺寸和形状重要的对象。当比例尺足够高以看到它们的区域时,城市边界、公园、建筑物轮廓或水体通常都被表示为多边形。道路和河流有时也可以表示为多边形。

以下SQL查询将返回与一个多边形相关联的几何图形(在:command:`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) 返回外环作为一个Linestring

  • ST_InteriorRingN(geometry,n) 返回指定的内部环作为一个Linestring

  • 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支持在大量格式中发出和消耗几何图形:

  • Well-known text (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

  • 可伸缩矢量图形 (SVG)

    • ST_AsSVG(geometry) 返回 text

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

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

以下SQL查询显示了一个:term:`WKB`表示的示例(调用:command:`encode()`是为了将二进制输出转换为ASCII形式以便打印):

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

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

由于WKT和WKB是在:term:`SFSQL`规范中定义的,它们不处理3维或4维几何图形。对于这些情况,PostGIS定义了扩展的常用文本(EWKT)和扩展的常用二进制(EWKB)格式。这些格式提供了与WKT和WKB相同的格式化功能,并添加了维度信息。

这是一个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,

  • 扩展的常用文本,并

  • ISO标准的常用文本。

在输出方面,:command:`ST_AsText`函数是保守的,并且只发出ISO标准的常用文本。

除了:command:`ST_GeometryFromText`函数之外,还有许多其他方法可以从常用文本或类似格式的输入创建几何图形:

-- 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. 从文本中解析

到目前为止,我们看到的:term:`WKT`字符串都是'text'类型,我们已经使用PostGIS函数如:command:`ST_GeomFromText()`将它们转换为'geometry'类型。

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

SELECT 0.9::text;

较不平凡的是,这个SQL将一个:term:`WKT`字符串转换为几何图形:

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

使用转换创建几何图形时需要注意的一点是:除非您指定SRID,否则您将获得一个具有未知SRID的几何图形。您可以使用"扩展"的常用文本形式指定SRID,该形式在前面包含一个SRID块:

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

在处理:term:WKTgeometry`和`geography`列(参见:ref:`geography)时,使用转换符号是非常常见的。

9.6. 函数列表

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

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

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

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

ST_AsEWKB: 返回具有SRID元数据的几何对象的Well-Known Binary(WKB)表示。

ST_AsEWKT: 返回具有SRID元数据的几何对象的Well-Known Text(WKT)表示。

ST_AsGeoJSON: 将几何对象返回为一个 GeoJSON 元素。

ST_AsGML: 将几何对象返回为一个 GML 版本 2 或 3 元素。

ST_AsKML: 将几何对象返回为一个 KML 元素。有几种变体。默认版本为2,默认精度为15。

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

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

ST_GeometryN: 如果几何对象是GEOMETRYCOLLECTION、MULTIPOINT、MULTILINESTRING、MULTICURVE或MULTIPOLYGON,则返回基于1的第N个几何对象。否则,返回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: 返回线串几何图形的第一个点作为一个点。

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

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