16. 投影数据¶
地球不是平的,没有简单的方法可以把它放在一张平坦的纸质地图(或电脑屏幕)上,所以人们想出了各种巧妙的解决方案,每种方案都有其优缺点。一些投影保留了面积,因此所有物体都具有相对大小;其他投影保留了角度(保角),例如墨卡托投影;一些投影试图找到一个良好的中间混合,在几个参数上只有很小的失真。所有投影的共同点是它们将(球面)世界转换为平面笛卡尔坐标系,选择哪种投影取决于你将如何使用数据。
当我们 加载 nyc 数据 时,我们已经遇到了投影。(回想一下那个讨厌的 SRID 26918)。然而,有时你需要在空间参考系之间进行转换和重新投影。PostGIS 包含对更改数据投影的内置支持,使用 ST_Transform(geometry, srid) 函数。为了管理几何图形上的空间参考标识符,PostGIS 提供了 ST_SRID(geometry) 和 ST_SetSRID(geometry, srid) 函数。
我们可以使用 ST_SRID 函数确认数据的 SRID
SELECT ST_SRID(geom) FROM nyc_streets LIMIT 1;
26918
那么“26918”的定义是什么?正如我们在“加载数据部分”中看到的,定义包含在 spatial_ref_sys
表中。事实上,那里有 **两个** 定义。“众所周知的文本” (WKT) 定义在 srtext
列中,在 proj4text
列中还有一个“proj.4”格式的定义。
SELECT * FROM spatial_ref_sys WHERE srid = 26918;
PostGIS 重新投影引擎将尝试从 spatial_ref_sys
表中找到最佳投影
auth_name / auth_srid 如果 proj 在其内部目录中找到有效的“授权名称”和“授权 srid”,它将使用它来生成投影定义。
srtext 如果 proj 可以从
srtext
中解析并形成定义对象,它将使用它。proj4text 最后,proj 将尝试处理
proj4text
。
所有这些冗余意味着,要创建新的投影,您只需要一个有效的 srtext
字符串或 proj4text
字符串。所有常见的授权名称/代码对默认情况下已加载到表中。
如果您在创建自定义投影时有选择,请填写 srtext
列,因为该列也被外部程序使用,例如 GeoServer、QGIS 和 FME 等。
16.1. 比较数据¶
总而言之,坐标和 SRID 定义了地球上的一个位置。没有 SRID,坐标只是一个抽象的概念。“笛卡尔”坐标系被定义为放置在地球表面的“平面”坐标系。由于 PostGIS 函数在这样的平面上工作,因此比较操作要求两个几何体都以相同的 SRID 表示。
如果您输入具有不同 SRID 的几何体,您只会得到错误。
SELECT ST_Equals(
ST_GeomFromText('POINT(0 0)', 4326),
ST_GeomFromText('POINT(0 0)', 26918)
);
ERROR: ST_Equals: Operation on mixed SRID geometries (Point, 4326) != (Point, 26918)
注意
小心不要过度使用 ST_Transform 进行动态转换。空间索引是使用存储的几何体的 SRID 构建的。如果比较是在不同的 SRID 中进行的,则空间索引(通常)不会被使用。最佳实践是为数据库中的所有表选择 **一个 SRID**。只有在读取或写入外部应用程序的数据时才使用转换函数。
16.2. 转换数据¶
如果我们回到 SRID 26918 的 proj4 定义,我们可以看到我们的工作投影是 UTM(通用横轴墨卡托)第 18 区,单位为米。
SELECT srtext FROM spatial_ref_sys WHERE srid = 26918;
PROJCS["NAD83 / UTM zone 18N",
GEOGCS["NAD83",
DATUM["North_American_Datum_1983",
SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6269"]],
PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4269"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-75],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1,AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],AXIS["Northing",NORTH],
AUTHORITY["EPSG","26918"]]
让我们将一些数据从我们的工作投影转换为地理坐标 - 也称为“经度/纬度”。
要将数据从一个 SRID 转换为另一个 SRID,您必须首先验证您的几何体是否具有有效的 SRID。由于我们已经确认了有效的 SRID,因此接下来我们需要要转换到的投影的 SRID。换句话说,地理坐标的 SRID 是什么?
地理坐标最常用的 SRID 是 4326,对应于“WGS84 椭球体上的经度/纬度”。您可以在此处查看定义
您也可以从 spatial_ref_sys
表中提取定义
SELECT srtext FROM spatial_ref_sys WHERE srid = 4326;
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]]
让我们将“Broad St”地铁站的坐标转换为地理坐标
SELECT ST_AsText(ST_Transform(geom,4326))
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(-74.01067146887341 40.70710481558761)
如果您加载数据或创建新的几何图形而没有指定 SRID,则 SRID 值将为 0。回想一下在 Geometries 中,当我们创建 geometries
表时,我们没有指定 SRID。如果我们查询数据库,我们应该期望所有 nyc_
表都具有 26918 的 SRID,而 geometries
表默认使用 0 的 SRID。
要查看表的 SRID 分配,请查询数据库的 geometry_columns
表。
SELECT f_table_name AS name, srid
FROM geometry_columns;
name | srid
---------------------+-------
nyc_census_blocks | 26918
nyc_homicides | 26918
nyc_neighborhoods | 26918
nyc_streets | 26918
nyc_subway_stations | 26918
geometries | 0
但是,如果您知道坐标的 SRID 应该是什么,您可以使用几何图形上的 ST_SetSRID 事后设置它。然后您将能够将几何图形转换为其他系统。
SELECT ST_AsText(
ST_Transform(
ST_SetSRID(geom,26918),
4326)
)
FROM geometries;
16.3. 函数列表¶
ST_AsText: 返回几何/地理图形的 Well-Known Text (WKT) 表示,不包含 SRID 元数据。
ST_SetSRID(geometry, srid): 将几何图形上的 SRID 设置为特定整数值。
ST_SRID(geometry): 返回 ST_Geometry 的空间参考标识符,如 spatial_ref_sys 表中定义。
ST_Transform(geometry, srid): 返回一个新的几何图形,其坐标已转换为整数参数引用的 SRID。