使用 PostGIS 时,为什么英国县的几何图形会出现在几内亚湾?

Amy*_*ett 3 postgresql postgis spatial-query amazon-web-services amazon-rds

我在 AWS Postgres 服务器中有两个表(我正在使用 DBeaver 进行查询)。

  • 表 1 是我从名为 的 S3 存储桶导入的 shapefile uk_counties,其中列出了英国所有县的几何图形(SRID = 27700 - shapefile 可以在此处找到)。

  • 表 2 被称为demand_origin并 包含字段origin_city(英国的地点)和两个字段latitudelongitude(其中包含 中地点的纬度和经度origin_city)。

通过加入uk_counties(shapefile) 和demand_origin,我想通过查找各自的经度与县的 shapefile 相交的位置,将一个县分配给英国的各个地方。

问题是这个连接一直显示为空。经过大量调查后,shapefile 中的几何图形似乎被映射到几内亚湾(纬度 = 0,经度 = 0 及其周围)。

请参阅莱斯特的 shapefile 作为示例:

在此输入图像描述

我的猜测是,几何图形使用的是北距/西距,而不是纬度/经度,因此 PostGIS 将这些形状映射到 lat=0、long=0 左右,因此可能需要重新校准。

以下是莱斯特和其他县的几何形状的片段:

ctua23nm 几何学
约克 多边形 ((464216.99650000036 462110.9015999995, 464266.20299999975 462093.0965999998, 464270.3008000003 462094.3962999992, 46428 9.8992999997 4
德比 多边形 ((434972.3005999997 341311.7999000009, 434986.3008000003 341310.40029999986, 435000.0536000002 341314.6991000008, 435015 .29860000033 3
剑桥郡 多多边形 (((529832.0997000001 300053.7999000009, 529880.2013999997 300039.1041000001, 529903.7987000002 300036.6048000008, 529 914.20399999

有什么问题吗?

Erm*_*ary 5

FWIW,当我从上面的链接下载 Shapefile 并像这样导入它时:

shp2pgsql -I -s 27700 -g geometry CTYUA_MAY_2023_UK_BFC.shp uk_counties | psql -d mydb
Run Code Online (Sandbox Code Playgroud)

我得到了一个非常不同的模式:

\d+ uk_counties
Run Code Online (Sandbox Code Playgroud)
   Column   |             Type             | Collation | Nullable |                 Default                  | Storage  | Compression | Stats target | Description
------------+------------------------------+-----------+----------+------------------------------------------+----------+-------------+--------------+-------------
 gid        | integer                      |           | not null | nextval('uk_counties_gid_seq'::regclass) | plain    |             |              |
 ctyua23cd  | character varying(9)         |           |          |                                          | extended |             |              |
 ctyua23nm  | character varying(36)        |           |          |                                          | extended |             |              |
 ctyua23nmw | character varying(24)        |           |          |                                          | extended |             |              |
 bng_e      | double precision             |           |          |                                          | plain    |             |              |
 bng_n      | double precision             |           |          |                                          | plain    |             |              |
 long       | double precision             |           |          |                                          | plain    |             |              |
 lat        | double precision             |           |          |                                          | plain    |             |              |
 globalid   | character varying(38)        |           |          |                                          | extended |             |              |
 geometry   | geometry(MultiPolygon,27700) |           |          |                                          | main     |             |              |
Indexes:
    "uk_counties_pkey" PRIMARY KEY, btree (gid)
    "uk_counties_geometry_idx" gist (geometry)
Access method: heap
Run Code Online (Sandbox Code Playgroud)

我可以轻松获得正确的纬度和经度值:

SELECT
    ctyua23nm,
    long,
    lat
FROM
    uk_counties
WHERE
    ctyua23nm = 'Leicester';
Run Code Online (Sandbox Code Playgroud)
 ctyua23nm |  long   |   lat
-----------+---------+---------
 Leicester | -1.1304 | 52.6359
(1 row)
Run Code Online (Sandbox Code Playgroud)

重新导入 Shapefile 可能会更容易,因为我不确定你是如何导入它的。

如果您坚持使用当前架构,请继续。


几何图形使用北距/西距,而不是纬度/经度

正确的。

SRID 27700 / EPSG:27700与英国地形测量局国家网格(OSGB) 或更通称的英国国家网格 (BNG)一致。它基本上使用以米为单位的投影东距和北距,而不是以度为单位的纬度和经度。

您可以通过运行看到这一点:

SELECT srtext FROM spatial_ref_sys WHERE srid = 27700;
Run Code Online (Sandbox Code Playgroud)
PROJCS["OSGB 1936 / British National Grid",
  GEOGCS["OSGB 1936",
    DATUM["OSGB_1936",
      SPHEROID["Airy 1830", 6377563.396, 299.3249646,
        AUTHORITY["EPSG", "7001"]],
      TOWGS84[446.448, -125.157, 542.06, 0.15, 0.247, 0.842, -20.489],
      AUTHORITY["EPSG", "6277"]],
    PRIMEM["Greenwich", 0, AUTHORITY["EPSG", "8901"]],
    UNIT["degree", 0.0174532925199433, AUTHORITY["EPSG", "9122"]],
    AUTHORITY["EPSG", "4277"]],
  PROJECTION["Transverse_Mercator"],
  PARAMETER["latitude_of_origin", 49],
  PARAMETER["central_meridian", -2],
  PARAMETER["scale_factor", 0.9996012717],
  PARAMETER["false_easting", 400000],
  PARAMETER["false_northing", -100000],
  UNIT["metre", 1, AUTHORITY["EPSG", "9001"]],
  AXIS["Easting", EAST],
  AXIS["Northing", NORTH],
  AUTHORITY["EPSG", "27700"]]
Run Code Online (Sandbox Code Playgroud)

注意UNIT["metre"AXIS["Easting", EAST]AXIS["Northing", NORTH]

您很可能希望使用 SRID 4326 / EPSG:4326来投影数据,它符合WGS84,即 GPS 标准。

它是一个二维地理坐标系,即使用纬度和经度。


要将 SRID 27700 表投影到纬度和经度坐标 (SRID 4326),请首先使用 验证列的 SRID 是否geometry设置为 SRID 27700 Find_SRID

SELECT
    Find_SRID ('public', 'uk_counties', 'geometry');
Run Code Online (Sandbox Code Playgroud)

输出应该是:

 find_srid
-----------
     27700
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果没有,请使用以下命令设置列的 SRID UpdateGeometrySRID

SELECT
    UpdateGeometrySRID ('uk_counties', 'geometry', 27700);
Run Code Online (Sandbox Code Playgroud)
                updategeometrysrid
---------------------------------------------------
 public.uk_counties.geometry SRID changed to 27700
(1 row)
Run Code Online (Sandbox Code Playgroud)

然后,使用ST_TransformPostGIS中的函数进行转换:

返回一个新的几何图形,其坐标转换为不同的空间参考系统。

ALTER TABLE uk_counties
    ALTER COLUMN geometry TYPE geometry(geometry, 4326)
    USING ST_Transform (geometry, 4326);
Run Code Online (Sandbox Code Playgroud)
ALTER TABLE
Run Code Online (Sandbox Code Playgroud)

完成后,我们可以通过以下方式从几何图形中获取纬度和经度:

  1. 用于ST_Centroid获取几何体的质心 - 一个点
  2. 应用ST_Y函数获取纬度
  3. 应用该ST_X函数来获取经度。

让我们创建 2 个新列来存储数据:

ALTER TABLE uk_counties
    ADD COLUMN latitude DOUBLE PRECISION,
    ADD COLUMN longitude DOUBLE PRECISION;
Run Code Online (Sandbox Code Playgroud)
ALTER TABLE
Run Code Online (Sandbox Code Playgroud)

然后,填充列...

UPDATE
    uk_counties
SET
    latitude = ST_Y (ST_Centroid (geometry)),
    longitude = ST_X (ST_Centroid (geometry));
Run Code Online (Sandbox Code Playgroud)
UPDATE 218
Run Code Online (Sandbox Code Playgroud)

现在,您有 2 个新列:

  • latitude
  • longitude

新列应具有正确的值:

UPDATE 218
Run Code Online (Sandbox Code Playgroud)
SELECT
    ctyua23nm,
    latitude,
    longitude
FROM
    uk_counties
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的一点是,以莱斯特城为例......

          ctyua23nm          |     latitude       |     longitude
-----------------------------+--------------------+---------------------
 Hartlepool                  | 54.669449373886266 | -1.2594048655284926
 Middlesbrough               |  54.54200444097641 | -1.2222619068734741
 Redcar and Cleveland        |  54.55165165356056 | -1.0206837926504952
 Stockton-on-Tees            |  54.56161339847885 | -1.3322804311895529
 Darlington                  | 54.548705061498694 | -1.5526287937957188
 Halton                      | 53.345131982125686 |  -2.712197804308062
 Warrington                  | 53.399109236880015 | -2.5627669775597606
 Blackburn with Darwen       | 53.692643404310815 |  -2.467582012742445
 Blackpool                   |  53.81779799751382 |  -3.029241917065863
 Kingston upon Hull, City of |  53.76405945136756 |  -0.334854807051097
(10 rows)
Run Code Online (Sandbox Code Playgroud)
SELECT
    ctyua23nm,
    latitudea,
    longitudea
FROM
    uk_counties
WHERE
    ctyua23nm = 'Leicester';
Run Code Online (Sandbox Code Playgroud)

这里是莱斯特!

在此输入图像描述