我正在使用Python和Cartopy创建地图应用程序,并尝试使用开放源地图图块作为背景,以具有比默认Cartopy地图更多的选项。
它非常适合放大得相当近的地图,但是当我尝试从更高的高度获取视图时,出现了一些故障。如果将缩放比例设置为11,则可以使用。如果将其设置为12,它将无限期挂起并且不提供任何追溯。
OSM和雄蕊地图服务器的结果相同。
这是一个简短的独立示例(请注意,一两行可能是我尝试过的各种方式的产物)
Dim YourRange As Range
'Whatever you're using to obtain a reference to it.
'...
Dim row As Long
For row = 13 To YourRange.Rows.Count
YourRange.Rows(row).AutoFit
If YourRange.Rows(row).RowHeight > 50 Then
YourRange.Rows(row).RowHeight = 50
End If
Next
结果,缩放= 7:
但是如果我将zoom更改为14,则无论我允许运行多长时间,该程序都不会完成。
传递给cimgt.OSM()的url参数是可选的。有或没有它我都会得到相同的结果。 (请参阅:https://scitools.org.uk/cartopy/docs/v0.16/cartopy/io/img_tiles.html#cartopy.io.img_tiles.OSM)
我在这里错过了什么吗?任何帮助将不胜感激,谢谢。
答案 0 :(得分:2)
"zoom" levels are based on a Quadtree。从本质上讲,提高“缩放”分辨率会使图块数量增加四倍。
所以:
zoom level 0: 4^0 = 1 tile(s) to cover the globe
zoom level 1: 4^1 = 4 tile(s) to cover the globe
...
zoom level 7: 4^7 = 16,384 tile(s) to cover the globe
...
zoom level 14: 4^14 = 268,435,456 tile(s) to cover the globe
因此,如果您要求在大范围内以高缩放级别使用图块,则最终可能会请求很多图块。
在Tiler对象上有一个有用的但未记录的方法,名为find_images
。它的实现不太繁琐:
https://github.com/SciTools/cartopy/blob/v0.16.0/lib/cartopy/io/img_tiles.py#L103-L122。
使用此方法,我们实际上可以看到用于给定范围的图块。重要的是,该范围需要在tiler(几乎是Web Mercator)的坐标系中提供。
In [1]: import cartopy.io.img_tiles as cimgt
In [2]: import shapely.geometry as sgeom
In [3]: import cartopy.crs as ccrs
In [4]: tiler = cimgt.OSM()
In [5]: pt = 45.068466, -66.45477
In [6]: target = sgeom.box(pt[0] - 1.5, pt[1] - 1.5, pt[0] + 1.5, pt[1] + 1.5)
In [7]: target_mercator = tiler.crs.project_geometry(target, ccrs.Geodetic()).geoms[0]
因此,有了所有的片段,我们就可以开始找出在特定的缩放级别上需要绘制哪些图块:
对于您要指定的目标,缩放级别为0,我们需要以下图块(x, y, z)
:
In [8]: list(tiler.find_images(target_mercator, 0))
Out[8]: [(0, 0, 0)]
对于z = 1,它仍然只是一个图块:
In [9]: list(tiler.find_images(target_mercator, 1))
Out[9]: [(1, 1, 1)]
但是对于z = 2,我们显然跨越了图块边界,因为我们现在需要两个图块来覆盖目标域:
In [10]: list(tiler.find_images(target_mercator, 2))
Out[10]: [(2, 2, 2), (2, 3, 2)]
Naturally, the list grows as we increase the zoom level:
In [11]: list(tiler.find_images(target_mercator, 3))
Out[11]: [(4, 5, 3), (5, 5, 3), (4, 6, 3), (5, 6, 3)]
In [12]: list(tiler.find_images(target_mercator, 6))
Out[12]: [(39, 47, 6), (40, 47, 6), (39, 48, 6), (40, 48, 6)]
当我们达到z = 7时,我们发现需要8个图块来表示相关区域:
In [13]: list(tiler.find_images(target_mercator, 7))
Out[13]:
[(79, 94, 7),
(79, 95, 7),
(80, 94, 7),
(80, 95, 7),
(79, 96, 7),
(79, 97, 7),
(80, 96, 7),
(80, 97, 7)]
我确定您可以看到前进的方向,但是让我们尝试使用14的缩放级别来找出我们需要多少个图块。为了节省电力和阅读时间,我们只需打印该列表的长度即可。
In [14]: len(list(tiler.find_images(target_mercator, 14)))
Out[14]: 47334
对,因此,要以所需的程度请求缩放级别14,将需要您以256x256(8位色图PNG)下载〜47,000个图块。 z = 0的图块(https://a.tile.openstreetmap.org/0/0/0.png)压缩后约为8882字节,因此,假设这是典型的情况,您最终将下载〜420420588字节(400MB)。为了将这些数据保存在内存中,您还需要约2.9GB的RAM。最后,要将这些数据重新投影到PlateCarree,您至少需要使此RAM数量增加一倍,这是假定高效的重新投影实现(不是cartopy的实现)。
希望这可以告诉您为什么您的代码似乎要花很长时间-您要让它完成很多工作。有人讨论过当请求过多数量的图块时,是否应警告Cartopy,但总会归结为一个不合理的数字(您可能实际上想要来获取那么多图块! )。我们还讨论了自动缩放级别选择-如果有足够的需求,这就是really feasible。
HTH