【问题标题】:How can I generate a regular geographic grid using python?如何使用 python 生成常规地理网格?
【发布时间】:2016-10-31 12:38:09
【问题描述】:

我想检索某个地图区域上常规网格的所有纬度/经度坐标对。我找到了 geopy 库,但根本没有解决这个问题。

例如,我有一个矩形地理区域,由其在纬度/经度坐标中的四个角描述,我试图计算间距为例如1km 覆盖这个区域。

【问题讨论】:

  • 像 NSEW 这样的基点?基点如何以(经度,纬度)对给出,它们如何有距离?请详细说明您的问题并添加您到目前为止的代码。
  • 对不起,我错了我想找到某个区域的所有经纬度坐标,例如我在谷歌地图中有一个区域的 4 点经纬度,我想检索所有经纬度坐标这片区域彼此相距10公里。我现在没有代码,我还在 geopy 中搜索。
  • 所以你想在给定多边形的情况下创建一个规则的网格点坐标?
  • 对,就是这个! geopy 或其他图书馆有什么吗?

标签: python google-maps geopy


【解决方案1】:

初步考虑

您的特定区域的定义方式略有不同。如果它只是一个矩形区域(注意:投影中的矩形不一定是地球表面上的矩形!),您可以使用所需的步长在两个坐标维度上简单地从最小值迭代到最大值。如果您手头有任意多边形形状,则需要测试生成的点中的哪一个与该多边形相交,并且只返回满足此条件的坐标对。

计算规则网格

规则网格不等于跨投影的规则网格。您正在谈论纬度/经度对,这是一个极坐标系,以近似地球表面形状的度数为单位。在纬度/经度 (EPSG:4326) 中,距离不是以米/公里/英里为单位,而是以度为单位。

此外,我假设您要计算一个网格,其“水平”步长平行于赤道(即纬度)。对于其他网格(例如旋转的矩形网格、与经度平行的垂直网格等),您需要花费更多的精力来转换您的形状。

问问自己:你想创建一个以度为单位还是以米为单位的规则间隔网格?

以度为单位的网格

如果你想要度数,你可以简单地迭代:

stepsize = 0.001
for x in range(lonmin, lonmax, stepsize):
    for y in range(latmin, latmax, stepsize):
        yield (x, y)

但是:请务必知道,以度为单位的步长以米为单位的长度在地球表面上是不同的。例如,靠近赤道的 0.001 delta 度在地表上的距离与靠近两极的距离不同。

以米为单位的网格

如果您希望以米为单位,您需要将输入区域(地图上的特定区域)的纬度/经度边界投影到支持以米为单位的距离的坐标系中。您可以使用Haversine formula 作为粗略的近似值来计算纬度/经度对之间的距离,但这不是您可以使用的最佳方法。

更好的是搜索合适的投影,将您感兴趣的区域转换为该投影,通过直接迭代创建网格,获取点,并将它们投影回纬度/经度对。例如,适合欧洲的预测是 EPSG:3035。顺便说一句,谷歌地图使用 EPSG:900913 作为他们的网络地图服务。

在 python 中,您可以使用库 shapelypyproj 来处理地理形状和投影:

import shapely.geometry
import pyproj

# Set up transformers, EPSG:3857 is metric, same as EPSG:900913
to_proxy_transformer = pyproj.Transformer.from_crs('epsg:4326', 'epsg:3857')
to_original_transformer = pyproj.Transformer.from_crs('epsg:4326', 'epsg:3857')

# Create corners of rectangle to be transformed to a grid
sw = shapely.geometry.Point((-5.0, 40.0))
ne = shapely.geometry.Point((-4.0, 41.0))

stepsize = 5000 # 5 km grid step size

# Project corners to target projection
transformed_sw = to_proxy_transformer.transform(sw.x, sw.y) # Transform NW point to 3857
transformed_ne = to_proxy_transformer.transform(ne.x, ne.y) # .. same for SE

# Iterate over 2D area
gridpoints = []
x = transformed_sw[0]
while x < transformed_ne[0]:
    y = transformed_sw[1]
    while y < transformed_ne[1]:
        p = shapely.geometry.Point(to_original_transformer.transform(x, y))
        gridpoints.append(p)
        y += stepsize
    x += stepsize

with open('testout.csv', 'wb') as of:
    of.write('lon;lat\n')
    for p in gridpoints:
        of.write('{:f};{:f}\n'.format(p.x, p.y))

这个例子生成了这个等间距的网格:

【讨论】:

  • 非常感谢,你已经很清楚了,你教会了我很多新东西,谢谢!
  • 你的代码有一个小错误:当写出到 testout.csv 时,流被定义为'wb',但是写入了一个字符串。它应该改为'w'。
  • 你把角落的名字弄混了。 nw 不是左上角而是左下角,因此是swse 相同,东北角(右上角)应命名为 ne
  • @Badmiral 我在 QGIS 中加载了生成的 CSV 并截取了屏幕截图,这对我来说是最快的解决方案。您也可以轻松使用matplotlib et al
  • 很好的解决方案。虽然有一个小错误 - to_original_transformer = pyproj.Transformer.from_crs('epsg:4326', 'epsg:3857') 应该是: to_original_transformer = pyproj.Transformer.from_crs('epsg:3857', 'epsg:4326')
猜你喜欢
  • 2018-05-23
  • 2019-11-07
  • 2016-02-02
  • 2018-11-23
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
相关资源
最近更新 更多