Базовая карта Python меняет разрешение при увеличении - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь изменить разрешение карты, когда пользователь увеличивает масштаб, чтобы сэкономить память и время обработки.Я попробовал следующий код, но, хотя разрешение карты меняется при каждом увеличении, рисунок не обновляется, и я застрял с грубым разрешением.Любые идеи о том, как заставить карту обновить свое разрешение, когда пользователь увеличивает масштаб?Спасибо!

Вот код, который я пробовал:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

# create new figure, axes instances
fig = plt.figure(dpi=150)
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# setup mercator map projection
map = Basemap(projection='merc',llcrnrlat=-58,urcrnrlat=80,
              llcrnrlon=-180,urcrnrlon=180,resolution='c')

map.drawcoastlines(linewidth=0.50)
map.fillcontinents()
map.drawmapboundary()

# Declare and register callbacks for zoom control
def on_lims_change(axes):
    xrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])
    yrange = abs(ax.get_xlim()[1] - ax.get_xlim()[0])

    # try to change map resolution based on zoom level
    if max(xrange,yrange) < 1E7 and max(xrange,yrange) > 1E6: # 'l' = low
        map.resolution = 'l'
    elif max(xrange,yrange) < 1E6 and max(xrange,yrange) > 5E5: # 'i' = intermeditate
        map.resolution = 'i'
    elif max(xrange,yrange) < 5E5 and max(xrange,yrange) > 1E5: # 'h' = high
        map.resolution = 'h'
    elif max(xrange,yrange) < 1E5: # 'f' = full
        map.resolution = 'f'
    else: # 'c' = coarse
        map.resolution = 'c'

    print(map.resolution)
    map.drawcoastlines(linewidth=0.50)
    map.fillcontinents()
    map.drawmapboundary()

ax.callbacks.connect('xlim_changed', on_lims_change)

plt.show()

1 Ответ

0 голосов
/ 15 марта 2019

Лучший способ, который я нашел, это вызвать что-то вроде

zoomcall = ax.callbacks.connect('ylim_changed', onzoom)
ax.patches.clear()
ax.collections.clear()
ax.callbacks.disconnect(zoomcall)

, чтобы (1) установить обратный вызов, (2) очистить старую карту и (3) очистить обратный вызов.Это сделано как часть нового класса для простоты использования.

Вот схема кода:

class ZoomPlot():

    def __init__(self, pnts):
        self.fig = plt.figure(figsize=(15,9))
        self.ax = self.fig.add_subplot(111)

        self.bnds = self.bnds_strt = [-58, 80, -180, 180]
        self.resolution = 'c'

        self.plot_map()

    def plot_map(self):
        self.map = Basemap(projection='merc',llcrnrlat=self.bnds[0],urcrnrlat=self.bnds[1],
                      llcrnrlon=self.bnds[2],urcrnrlon=self.bnds[3],resolution=self.resolution)

        self.map.drawcoastlines()
        self.map.drawmapboundary(fill_color='cornflowerblue')
        self.map.fillcontinents(color='lightgreen', lake_color='aqua')
        self.map.drawcountries()
        self.map.drawstates()

        self.plot_points()

        self.fig.canvas.draw()

        self.zoomcall = self.ax.callbacks.connect('ylim_changed', self.onzoom)

    def onzoom(self, axes):
        #print('zoom triggered')
        self.ax.patches.clear()
        self.ax.collections.clear()
        self.ax.callbacks.disconnect(self.zoomcall)

        x1, y1 = self.map(self.ax.get_xlim()[0], self.ax.get_ylim()[0], inverse = True)
        x2, y2 = self.map(self.ax.get_xlim()[1], self.ax.get_ylim()[1], inverse = True)
        self.bnds = [y1, y2, x1, x2]

        # reset zoom to home (workaround for unidentified error when you press the home button)
        if any([a/b > 1 for a,b in zip(self.bnds,self.bnds_strt)]):
            self.bnds = self.bnds_strt # reset map boundaryies
            self.ax.lines.clear() # reset points
            self.ab.set_visible(False) # hide picture if visible

        # change map resolution based on zoom level
        zoom_set = max(abs(self.bnds[0]-self.bnds[1]),abs(self.bnds[2]-self.bnds[3]))
        if zoom_set < 30 and zoom_set >= 3:
            self.resolution = 'l'
            #print('   --- low resolution')
        elif zoom_set < 3:
            self.resolution = 'i'
            #print('   --- intermeditate resolution')
        else:
            self.resolution = 'c'
            #print('   --- coarse resolution')

        self.plot_map()
...