Удалить старого художника в FuncAnimation of Matplotlib - PullRequest
0 голосов
/ 26 апреля 2020

Я создаю анимацию на карте-карте. Карта показывает орбиту спутника Земли с интервалом = 1с. В своем коде я добавил спутник на карту, используя класс AnnotationBbox и метод add_artist, как показано ниже. Проблема в том, что каждую 1 секунду карта обновляет новый спутник, не удаляя старый, поэтому на карте появляется полоса, как на картинке (под кодом). Как я могу это исправить ? Большое спасибо за вашу помощь.

import matplotlib.pyplot as plt
import cartopy.crs as crs
import cartopy
from matplotlib.offsetbox import AnnotationBbox, OffsetImage
from PIL import Image
from skyfield.api import EarthSatellite, Topos, load
import time
from matplotlib.animation import FuncAnimation
###############################################################################

# Get information of satellite
line1 = '1 25544U 98067A   14020.93268519  .00009878  00000-0  18200-3 0  5082'
line2 = '2 25544  51.6498 109.4756 0003572  55.9686 274.8005 15.49815350868473'

satellite = EarthSatellite(line1, line2, name='ISS (ZARYA)')

# cartopy map
fig = plt.figure(figsize=(10, 5))
ax = plt.axes(projection=crs.PlateCarree())
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.OCEAN)
ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=.5)
ax.add_feature(cartopy.feature.LAKES, alpha=0.95)
ax.coastlines()
ax.stock_img()

# Read satellite image
img = Image.open('sat.png')
ax.set_global()

#####################################################################

def animate(i): 

    # Get coordinate of satellite every 1 second
    ts = load.timescale()
    t = ts.now()
    geometry = satellite.at(t)
    subpoint = geometry.subpoint()
    lat = subpoint.latitude.degrees
    lon = subpoint.latitude.degrees

    # Add satellite on the cartopy map
    imagebox = OffsetImage(img, zoom=0.03)
    imagebox.image.axes = ax
    ab = AnnotationBbox(imagebox, [lat, lon], pad=0, frameon=False)
    ax.add_artist(ab)
    return ax

ani = FuncAnimation(ax.figure,
                    animate,
                    frames=10000,
                    interval=1000, blit=False, repeat=False) 

plt.show()

streak on the map

1 Ответ

1 голос
/ 28 апреля 2020

То, как вы это структурировали, означает, что он добавляет новые OffsetImage и AnnotationBbox к графику каждую секунду. Способ FuncAnimation предназначен для использования в том, что вы просто должны корректировать базовые данные (например, положение) соответствующих частей графика. Примерно так должно работать:

imagebox = OffsetImage(img, zoom=0.03)
imagebox.image.axes = ax
ab = AnnotationBbox(imagebox, [0, 0], pad=0, frameon=False)
ax.add_artist(ab)

def animate(i): 
    # Get coordinate of satellite every 1 second
    ts = load.timescale()
    t = ts.now()
    geometry = satellite.at(t)
    subpoint = geometry.subpoint()
    lat = subpoint.latitude.degrees
    lon = subpoint.latitude.degrees
    ab.xy = [lon, lat]
    return ab,

ani = FuncAnimation(ax.figure,
                    animate,
                    frames=10000,
                    interval=1000, blit=False, repeat=False) 

plt.show()
...