16. 投影数据¶
地球不是平坦的,也没有简单的方法可以将其绘制在平坦的纸质地图(或计算机屏幕)上,因此人们想出了各种巧妙的解决方案,每种方案都有利有弊。有些投影保留面积,因此所有对象都具有彼此的相对大小;其他投影保留角度(等角),如墨卡托投影;一些投影试图找到在几个参数上只有很小失真的良好中间混合。所有投影的共同点是它们将(球形)世界转换到平面笛卡尔坐标系上,选择哪种投影取决于您将如何使用数据。
当我们 加载 nyc 数据 <loading_data>`时,我们已经遇到了投影。 (回想一下那个讨厌的 SRID 26918)。然而,有时您需要在空间参考系统之间进行转换和重新投影。 PostGIS 包含使用 :command:`ST_Transform(geometry, srid) 函数更改数据投影的内置支持。为了管理几何上的空间参考标识符,PostGIS 提供了 ST_SRID(geometry) 和:command:`ST_SetSRID(geometry, srid)`函数。
我们可以使用 :command:`ST_SRID`函数确认数据的 SRID :
SELECT ST_SRID(geom) FROM nyc_streets LIMIT 1;
26918
“26918”的定义是什么?正如我们在“加载空间数据 <loading_data>”中看到的,定义包含在``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
。
所有这些冗余意味着在 PostGIS 中创建新投影所需的只是有效的 srtext
字符串或 ``proj4text``字符串。默认情况下,所有常见权限名称/代码对均已加载到表中。
如果您在创建自定义投影时可以选择,请填写``srtext``列,因为该列也由 GeoServer, QGIS,和 `FME <http://www.safe.com/>`等外部程序使用。
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)
注解
小心不要过于高兴地使用:command:ST_Transform 进行即时转换。空间索引是使用存储的几何图形的 SRID 构建的。如果在不同的 SRID 中进行比较,则(通常)不使用空间索引。最佳实践是为数据库中的所有表选择**一个 SRID**。仅当您向外部应用程序读取或写入数据时才使用转换函数。
16.2. 转换数据¶
如果我们返回到 SRID 26918 的 proj4 定义,我们可以看到我们的工作投影是 18 区的 UTM(通用横轴墨卡托),以米为测量单位。
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 是 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。回想一下几何:ref:geometries,当我们创建``geometries``表时,我们没有指定 SRID。如果我们查询数据库,我们应该期望所有``nyc_``表的 SRID 为 26918,而g``geometries`` 表的默认 SRID 为 0。
要查看表的 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 应该是什么,则可以在几何体上使用 :command:`ST_SetSRID`事后设置它。然后您将能够将几何图形转换为其他系统。
SELECT ST_AsText(
ST_Transform(
ST_SetSRID(geom,26918),
4326)
)
FROM geometries;
16.3. 函数列表¶
ST_AsText: 返回几何/地理对象的不带SRID元数据的Well-Known Text(WKT)表示。
ST_SetSRID(geometry, srid): 将几何体上的 SRID 设置为特定整数值。
ST_SRID(geometry): 返回 Spatial_ref_sys 表中定义的 ST_Geometry 的空间参考标识符。
ST_Transform(geometry, srid):返回一个新的几何图形,其坐标转换为整数参数引用的 SRID。