Python 使用cartopy和自然地球10m数据检查地理坐标点是陆地还是海洋

Python 使用cartopy和自然地球10m数据检查地理坐标点是陆地还是海洋,python,shapely,cartopy,Python,Shapely,Cartopy,前面问题“使用cartopy检查地理坐标点是陆地还是海洋”的答案请参见建议使用以下代码确定地理坐标点是否为“陆地”: 当自然地球“物理”“陆地”形状文件的分辨率更改为“10m”时,此代码返回地理坐标(0,0)的意外的结果“True” 这是自然地球shapefile数据还是shapely实用程序代码的问题 print shapely.__version__ 1.6.4.post1 好奇。我肯定见过一元联合产生无效几何体的情况。在这种情况下运行land\u geom.is\u va

前面问题“使用cartopy检查地理坐标点是陆地还是海洋”的答案请参见建议使用以下代码确定地理坐标点是否为“陆地”:

当自然地球“物理”“陆地”形状文件的分辨率更改为“10m”时,此代码返回地理坐标(0,0)的意外的结果“True”

这是自然地球shapefile数据还是shapely实用程序代码的问题

    print shapely.__version__
    1.6.4.post1

好奇。我肯定见过
一元联合
产生无效几何体的情况。在这种情况下运行
land\u geom.is\u valid
需要花费大量时间,但实际上表明它是有效的几何体。如果有疑问,GEOS/Shapely的常见技巧是按0进行缓冲,这通常会产生一个改进的几何体,它以改进的形式表示我们以前拥有的几何体。这样做还可以生成有效的几何图形

不幸的是,结果仍然是。。。查询继续报告在0,0

在这一点上,我有点不知所措。如果有疑问,总是值得看一看数据。为了理智起见,我和他核实了一下。接下来,我查看了使用以下代码生成的几何体:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt

ax = plt.subplot(1, 2, 1, projection=ccrs.PlateCarree())
ax.add_geometries([b], ccrs.PlateCarree(), facecolor='green', edgecolor='none')

ax = plt.subplot(1, 2, 2, projection=ccrs.PlateCarree())
ax.add_geometries([b], ccrs.PlateCarree(), facecolor='green', edgecolor='none')
box_size = 5e-2
ax.set_extent([-box_size, box_size, -box_size, box_size])
ax.xaxis.set_visible(True)
ax.yaxis.set_visible(True)

看哪,似乎有一块面积约为1英里^2的正方形土地,正好位于0,0!阴谋论者会为这样的想法感到高兴:这可能是一块被主流媒体用来对外星人进行军事研究的真正的土地,猫王的家园,但我怀疑更普通的答案是,数据中存在缺陷(或者可能是读取数据的工具中存在缺陷)

接下来,我使用进行了快速调查,查看它是否也加载给定区域的几何体:

import fiona
c = fiona.open(land_shp_fname)
hits = list(c.items(bbox=(-0.01, -0.01, 0.01, 0.01)))
len(hits)
hits
结果是确定的。。。这里确实有一个几何体,它甚至比图中显示的更小(可能是由于缓冲区的浮点公差):

快速搜索这个地方的名字“空岛”,让我感到恐怖的是,这是一个故意的数据怪癖。。。详细描述了空岛从深海升起的情况(事实上接近5000米)

那么,除了接受这一怪癖并承认在0,0处着陆,我们还能做什么呢?好吧,我们可以试着把它过滤掉

因此,使用您的代码并稍微调整一下:

land_shp_fname = shpreader.natural_earth(
    resolution='10m', category='physical', name='land')

land_geom = unary_union(
    [record.geometry
     for record in shpreader.Reader(land_shp_fname).records()
     if record.attributes.get('featurecla') != "Null island"])

land = prep(land_geom)

def is_land(x, y):
   return land.contains(sgeom.Point(x, y))
我们最终得到了一个函数,该函数以1:10000000(10m)的比例评估自然地球数据集,以确定一个点是海还是陆,而不考虑来自自然地球数据集的空岛异常

>>> print(is_land(0, 0))
False

Null Island已添加为疑难解答国家/地区


更正:上一个问题“使用cartopy检查地理坐标点是陆地还是海洋”的网站应
[(9,
  {'type': 'Feature',
   'id': '9',
   'geometry': {'type': 'Polygon',
    'coordinates': [[(-0.004789435546374336, -0.004389928165484299),
      (-0.004789435546374336, 0.00481690381926197),
      (0.004328009720073429, 0.00481690381926197),
      (0.004328009720073429, -0.004389928165484299),
      (-0.004789435546374336, -0.004389928165484299)]]},
   'properties': OrderedDict([('featurecla', 'Null island'),
                ('scalerank', 100),
                ('min_zoom', 100.0)])})]
land_shp_fname = shpreader.natural_earth(
    resolution='10m', category='physical', name='land')

land_geom = unary_union(
    [record.geometry
     for record in shpreader.Reader(land_shp_fname).records()
     if record.attributes.get('featurecla') != "Null island"])

land = prep(land_geom)

def is_land(x, y):
   return land.contains(sgeom.Point(x, y))
>>> print(is_land(0, 0))
False