介绍
在开始处理数据之前,让我们看一些简单的例子。 继续并在控制台中执行以下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;
执行后看到如下效果:
上面的示例创建一个表(几何),然后插入五个几何:一个点,一条线,一个多边形,一个带孔的多边形和一个集合。 最后,选择插入的行并显示在“输出”窗格中。
元数据表
与SQL的简单功能(SFSQL)规范一致,PostGIS提供了两个表来跟踪和报告给定数据库中可用的几何类型。
- 第一个表
spatial_ref_sys
定义了数据库已知的所有空间参考系统,稍后将对其进行详细描述。 - 第二个表(实际上是一个视图)
geometry_columns
提供了所有“特征”(定义为具有几何属性的对象)的列表,以及这些特征的基本详细信息。
表关系
让我们看一下数据库中的geometry_columns表。
SELECT * FROM geometry_columns;
输出如下:
f_table_catalog
,f_table_schema
和f_table_name
提供包含给定几何图形的特征表的完全限定名称。 由于PostgreSQL不使用目录,因此f_table_catalog
倾向于为空。f_geometry_column
是几何包含列的列的名称-对于具有多个几何列的要素表,每个记录都有一个记录。coord_dimension
和srid
分别定义几何的尺寸(2维,3维或4维)和空间参考系统标识符,该标识符参考了space_ref_sys
表。
类型列定义了几何类型,如下所述;
到目前为止,我们已经看到了Point和Linestring类型。
通过查询该表,GIS客户端和库可以确定检索数据时的期望值,并且可以执行任何必要的投影,处理或渲染,而无需检查每个几何。
现实世界中的物体
代表真实世界的对象
SQL的简单功能(SFSQL)规范是PostGIS开发的原始指导标准,它定义了表示真实对象的方式。 通过采用连续的形状并将其以固定的分辨率数字化,我们可以实现对象的可传递表示。 SFSQL仅处理二维表示形式。 PostGIS已将其扩展到包括3维和4维表示形式。 最近,SQL多媒体第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
点
一个空间点代表地球上的单个位置。 该点由一个坐标表示(包括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查询将返回与一个点关联的几何(在ST_AsText
列中)。
SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
LIMIT 1;
Linestrings 线
线串是位置之间的路径。 它采用两个或多个点的有序序列的形式。 道路和河流通常以线串表示。
如果线串在同一点开始和结束,则称其为闭合线。
如果它不交叉或不接触自身,则说起来很简单(如果闭合则在其端点处除外)。 线串可以是封闭的也可以是简单的。
纽约的街道网络(nyc_streets
)已在研讨会的早期加载。
该数据集包含名称和类型等详细信息。
一条现实世界的街道可能由许多线串组成,每个线串代表具有不同属性的一段道路。
以下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
Polygons 多边形
多边形代表一个区域。 多边形的外边界由环表示。
该环是一个线串,如上所述,线串既封闭又简单。
多边形内的孔也用环表示。
多边形用于表示大小和形状很重要的对象。
当比例尺足够高以查看其区域时,城市范围,公园,建筑足迹或水域通常都表示为多边形。 道路和河流有时可以表示为多边形。
以下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系统在允许多边形显式具有孔洞方面相对独特。
一些用于多边形的特定空间功能是:
ST_Area(geometry)
返回多边形的面积ST_NRings(geometry)
返回环的数量(通常为1,其中有更多的是孔)ST_ExteriorRing(geometry)
将外环作为线串返回ST_InteriorRingN(geometry,n)
返回指定的内部环作为线串ST_Perimeter(geometry)
返回所有环的长度
我们可以使用area函数来计算多边形的面积:
SELECT name, ST_Area(geom)
FROM geometries
WHERE name LIKE 'Polygon%';
Polygon 1
PolygonWithHole 99
请注意,带有孔的多边形的面积等于外壳面积(10x10平方)减去孔的面积(1x1平方)。
Collections 集合
共有四种收集类型,它们将多个简单几何形状分组。
MultiPoint
,点的集合MultiLineString
,线串的集合MultiPolygon
,多边形的集合GeometryCollection
,任何几何的异构集合(包括其他集合)
集合是在GIS软件中比在通用图形软件中显示更多的另一个概念。 它们对于将真实世界的对象直接建模为空间对象很有用。 例如,如何对通过路权分割的批次建模? 作为MultiPolygon
,一部分在路权的两侧。
我们的示例集合包含一个多边形和一个点:
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)))
用于集合的一些特定空间功能是:
ST_NumGeometries(geometry)
返回集合中的零件数ST_GeometryN(geometry,n)
返回指定的部分ST_Area(geometry)
返回所有多边形部分的总面积ST_Length(geometry)
返回所有线性零件的总长度
Geometry对象的输入输出
在数据库中,几何图形以PostGIS程序仅使用的格式存储在磁盘上。为了使外部程序能够插入和检索有用的几何,需要将其转换为其他应用程序可以理解的格式。幸运的是,PostGIS支持多种格式的发射和使用几何:
- 众所周知的(WKT)
ST_GeomFromText(text,srid)
返回GeometryST_AsText(geometry)
返回文本ST_AsEWKT(geometry)
返回文本
- 知名二进制文件(WKB)
ST_GeomFromWKB(bytea)
返回GeometryST_AsBinary(geometry)
返回byteaST_AsEWKB(geometry)
返回bytea
- 地理标记语言(GML)
ST_GeomFromGML(text)
返回GeometryST_AsGML(geometry)
返回文本
- 锁孔标记语言(KML)
ST_GeomFromKML(text)
返回GeometryST_AsKML(geometry)
返回文本
- GeoJSON
ST_AsGeoJSON(geometry)
返回文本
- 可缩放矢量图形(SVG)
ST_AsSVG(geometry)
返回文本
构造函数最常见的用途是将几何图形的文本表示形式转换为内部表示形式:
SELECT ST_GeomFromText('POINT(583571 4506714)',26918);
请注意,除了带有几何图形表示的文本参数外,我们还有一个数字参数,提供了几何图形的SRID。
以下SQL查询显示了WKB表示形式的示例(将二进制输出转换为ASCII形式进行打印时,需要调用encode()):
SELECT encode(
ST_AsBinary(ST_GeometryFromText('LINESTRING(0 0,1 0)')),
'hex');
01020000000200000000000000000000000000000000000000000000000000f03f0000000000000000
在本课程中,我们将继续使用WKT以确保您可以阅读和理解我们正在查看的几何。 但是,在大多数实际过程中,例如在GIS应用程序中查看数据,将数据传输到Web服务或远程处理数据,WKB是首选格式。
由于WKT和WKB是在SFSQL规范中定义的,因此它们不处理3维或4维几何。 对于这些情况,PostGIS定义了扩展的众所周知的文本(EWKT)和扩展的众所周知的二进制(EWKB)格式。 它们提供了与WKT和WKB相同的格式化功能,并增加了尺寸。
这是WKT中3D线串的示例:
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标准知名文本。
在输出端,ST_AsText函数是保守的,仅发出ISO标准的知名文本。
除了ST_GeometryFromText函数外,还有许多其他方法可以从众所周知的文本或类似格式的输入中创Geometry:
-- 使用 ST_GeomFromText 包含 SRID 参数
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>'));
从文本转换
到目前为止,我们已经看到的WKT字符串的类型为“文本”,我们已经使用诸如ST_GeomFromText()的PostGIS函数将其转换为“几何”类型。
PostgreSQL包括一种短格式语法,该语法允许将数据从一种类型转换为另一种类型,即转换语法oldata :: newtype
。 因此,例如,此SQL将double转换为文本字符串。
SELECT 0.9::text;
不那么简单,此SQL将WKT字符串转换为几何:
SELECT'POINT(0 0)':: geometry;
使用铸造创建几何时需要注意的一件事:除非指定SRID,否则将获得具有未知SRID的几何。 您可以使用“扩展的”众所周知的文本格式来指定SRID,该格式在前面包括一个SRID块:
SELECT'SRID = 4326; POINT(0 0)':: geometry;
在使用WKT以及几何和地理列(请参见地理)时,通常使用浇铸符号。
附加练习
为了帮助您进行以下练习,我们在本页底部提供了一些相关功能文档的链接列表。
这是对我们现有表格的提醒:
nyc_census_blocks
blkid, popn_total, boroname, geom
nyc_streets
name, type, geom
nyc_subway_stations
name, geom
nyc_neighborhoods
name, boroname, geom
练习
“'西村’附近的面积是多少?”
SELECT ST_Area(geom)
FROM nyc_neighborhoods
WHERE name = 'West Village';
-------------------------------
1044614.5296486
注意
面积以平方米为单位。 要获得以公顷为单位的面积,请除以10000。要得到以英亩为单位的面积,请除以4047。
“曼哈顿的面积是多少英亩?” (提示:nyc_census_blocks
和nyc_neighborhoods
在其中都具有boroname
。)
SELECT Sum(ST_Area(geom)) / 4047
FROM nyc_neighborhoods
WHERE boroname = 'Manhattan';
----------------------------------
13965.3201224118
或者
SELECT Sum(ST_Area(geom)) / 4047
FROM nyc_census_blocks
WHERE boroname = 'Manhattan';
-----------------------------------
14601.3987215548
“纽约市有多少人口普查区有一个洞?”
SELECT Count(*)
FROM nyc_census_blocks
WHERE ST_NumInteriorRings(ST_GeometryN(geom,1)) > 0;
-----------------------------------
43
注意
ST_NRings()函数可能很吸引人,但是它也计算多面的外圈和内圈。 为了运行
ST_NumInteriorRings()
,我们需要将块的MultiPolygon几何形状转换为简单的多边形,因此我们使用ST_GeometryN()
从每个集合中提取第一个多边形。 !
“纽约市的街道总长度(以公里为单位)是多少?” (提示:空间数据的度量单位为米,一公里中有1000米。)
SELECT Sum(ST_Length(geom)) / 1000
FROM nyc_streets;
------------------------------------
10418.9047172
“‘哥伦布赛尔’(哥伦布圆环)多长时间了?
SELECT ST_Length(geom)
FROM nyc_streets
WHERE name = 'Columbus Cir';
------------------------------------
308.34199
“'West Village’边界的JSON表示是什么?”
SELECT ST_AsGeoJSON(geom)
FROM nyc_neighborhoods
WHERE name = 'West Village';
{"type":"MultiPolygon","coordinates":
[[[[583263.2776595836,4509242.6260239873],
[583276.81990686338,4509378.825446927], ...
[583263.2776595836,4509242.6260239873]]]]}
几何类型是“ MultiPolygon”,很有趣!
“'West Village’多多边形中有多少个多边形?”
SELECT ST_NumGeometries(geom)
FROM nyc_neighborhoods
WHERE name = 'West Village';
------------------------------------
1
注意
在空间表中找到单元素MultiPolygon并不少见。 使用MultiPolygons允许仅具有一种几何类型的表存储单几何和多几何,而无需使用混合类型。
“按类型汇总的纽约市街道长度是多少?”
SELECT type, Sum(ST_Length(geom)) AS length
FROM nyc_streets
GROUP BY type
ORDER BY length DESC;
------------------------------------------------
type | length
------------+------------------
residential | 8629870.33786606
motorway | 403622.478126363
tertiary | 360394.879051303
motorway\_link | 294261.419479668
secondary | 276264.303897926
unclassified | 166936.371604458
primary | 135034.233017947
footway | 71798.4878378096
service | 28337.635038596
trunk | 20353.5819826076
cycleway | 8863.75144825929
pedestrian | 4867.05032825026
construction | 4803.08162103562
residential; motorway\_link | 3661.57506293745
trunk\_link | 3202.18981240201
primary\_link | 2492.57457083536
living\_street | 1894.63905457332
primary; residential; motorway\_link; residential | 1367.76576941335
undefined | 380.53861910346
steps | 282.745221342127
motorway\_link; residential | 215.07778911517\
注意
ORDER BY length DESC子句按长度降序对结果进行排序。 结果是大多数流行类型在列表中排在第一位。