上一个问题“使用Cartopy检查地理坐标点是陆地还是海洋”的答案,请参见https://stackoverflow.com/questions/asktitle=Checking%20if%20a%20geocoordinate%20point%20is%20land%20or%20ocean%20using%20cartopy%20and%20Natural%20Earth%2010m%20data,建议使用以下代码确定地理坐标是否为“ is_land”:
import cartopy.io.shapereader as shpreader
import shapely.geometry as sgeom
from shapely.ops import unary_union
from shapely.prepared import prep
land_shp_fname = shpreader.natural_earth(resolution='50m',
category='physical', name='land')
land_geom =
unary_union(list(shpreader.Reader(land_shp_fname).geometries()))
land = prep(land_geom)
def is_land(x, y):
return land.contains(sgeom.Point(x, y))
当“自然”“物理”“陆地”形状文件的分辨率更改为“ 10m”时,此代码将返回“ true”的地理结果(0,0)的意外结果。 / p>
>>> print(is_land(0, 0))
True
这是Natural Earth shapefile数据还是整齐的实用程序代码的问题?
print shapely.__version__
1.6.4.post1
答案 0 :(得分:2)
很好奇。我肯定已经看到unary_union
产生无效几何的情况。在这种情况下,运行land_geom.is_valid
会花费大量时间,但实际上表明它是有效的几何体。如有疑问,GEOS / Shapely的常见技巧是将缓冲区缓冲为0,这通常会导致改进的几何形状以改进的形式表示我们以前拥有的几何形状。这样做还声称可以产生有效的几何形状。
不幸的是,结果仍然存在...查询继续报告在0,0处有土地...
在这一点上,我有点茫然。如有疑问,总是值得一看的数据。为了保持理智,我与Google maps to confirm that there is definitely no land at 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!阴谋理论家会对这样的想法感到高兴,认为这可能是用于军事研究外星人和猫王之家的主流媒体擦洗掉的一块真正的土地,但我怀疑更平凡的答案是数据中有一个错误(或也许在读取数据的工具中。)
接下来,我使用fiona进行了快速调查,以查看它是否也加载了给定区域的几何图形:
import fiona
c = fiona.open(land_shp_fname)
hits = list(c.items(bbox=(-0.01, -0.01, 0.01, 0.01)))
len(hits)
hits
结果是确定的……这里确实有一个几何图形,它甚至比图形显示的还要小(可能是由于缓冲区的浮点公差所致?)
[(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)])})]
快速搜索“空岛”(Null Island)这个地方的名称,令我感到恐惧的是,这是对数据的故意怪异... https://en.wikipedia.org/wiki/Null_Island和https://blogs.loc.gov/maps/2016/04/the-geographical-oddity-of-null-island/详细介绍了Null Island从何而来深处(实际上接近5000m)。
那么,除了接受这个怪癖并在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:10,000,000比例尺(10m)评估自然地球数据集,以确定一个点是海洋还是陆地,而没有考虑到来自自然地球数据集的零星岛奇数。 / p>
>>> print(is_land(0, 0))
False
答案 1 :(得分:0)