B. *_*eas 4 python shapely cartopy
上一个问题“使用 cartopy 检查地理坐标点是陆地还是海洋”的答案请参阅https://stackoverflow.com/questions/asktitle=Checking%20if%20a%20geocooperative%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))
Run Code Online (Sandbox Code Playgroud)
当自然地球“物理”“土地”形状文件的分辨率更改为“10m”时,此代码返回地理坐标 (0,0) 的意外结果“True”。
>>> print(is_land(0, 0))
True
Run Code Online (Sandbox Code Playgroud)
这是 Natural Earth shapefile 数据或 shapely 实用程序代码的问题吗?
print shapely.__version__
1.6.4.post1
Run Code Online (Sandbox Code Playgroud)
好奇的。我确实见过产生无效几何形状的情况unary_union。在这种情况下运行land_geom.is_valid需要花费大量时间,但实际上表明它是有效的几何图形。如果有疑问,GEOS/Shapely 的常见技巧是缓冲 0,这通常会导致改进的几何图形,以改进的形式表示我们之前拥有的几何图形。这样做还声称可以产生有效的几何图形。
不幸的是,结果仍然是...查询继续报告在 0, 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)
Run Code Online (Sandbox Code Playgroud)
看哪,有一块大小约为 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
Run Code Online (Sandbox Code Playgroud)
结果是确定的......这里确实有一个几何图形,而且它甚至比绘图显示的还要小(可能是由于缓冲区的浮点容差?):
[(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)])})]
Run Code Online (Sandbox Code Playgroud)
令我恐惧的是,快速搜索这个地方的名称“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))
Run Code Online (Sandbox Code Playgroud)
我们最终得到了一个以 1:10,000,000 比例 (10m) 评估自然地球数据集的函数,以确定一个点是海洋还是陆地,而不考虑来自自然地球数据集的空岛奇数。
>>> print(is_land(0, 0))
False
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1300 次 |
| 最近记录: |