如何为matplotlib的drawgreatcircle函数添加动画效果?

7
我创建了一个小程序,它接受一个 NHL 城市,并绘制球队在整个赛季中旅行的路径。生成的图形有些混乱:

Messy Graphic

所以我想到了一个有趣的想法,如果我将飞行路径动画化,就像看《印第安纳琼斯》电影一样,线从一个点到另一个点。

通过查看其他matplotlib示例,我的理解是动画函数接受一个函数,计算其输出,然后更新图形。但是我不知道如何在drawgreatcircle中实现这一点,因为每次调用它时,我都会得到一条完成的线。

你有什么想法可以帮助我解决这个问题吗?

以下是示例代码中的样本图像

Sample Image

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

fig = plt.figure(figsize=(10, 10))
m = Basemap(projection='merc', resolution=None,
                    llcrnrlon=-125, llcrnrlat=25, # LL = lower left
                    urcrnrlon=-60, urcrnrlat=55) #UR = upper right 
m.etopo(scale=0.5, alpha=0.5)


# Ottawa to Anaheim
# Ottawa
lat1 = 45.4215
lon1 = -75.6972

# Anaheim
lat2 = 33.8353
lon2 = -117.9145

m.drawgreatcircle(lon1,lat1,lon2,lat2)

如果你不太在意数学细节,那么在纬度和经度上进行线性插值应该是可以的,只要避免极点就行。 - f5r5e5d
什么是线性插值? - Bryan Stafford
什么是NHL城市? - ImportanceOfBeingErnest
一个拥有国家冰球联盟(NHL)球队的城市。 - Bryan Stafford
1个回答

3

drawgreatcicle 函数返回 matplotlib 的 line2D 对象,可以使用 get_data 方法获取数据。因此,思路是绘制大圆,获取数据,然后删除它。使用这些数据,可以对数组进行迭代,执行动画操作。

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

fig = plt.figure(figsize=(6, 4))
m = Basemap(projection='merc', resolution=None,
                    llcrnrlon=-125, llcrnrlat=25, # LL = lower left
                    urcrnrlon=-60, urcrnrlat=55) #UR = upper right 
m.etopo(scale=0.5, alpha=0.5)

# Ottawa to Anaheim
# Ottawa
lat1 = 45.4215
lon1 = -75.6972

# Anaheim
lat2 = 33.8353
lon2 = -117.9145

line, = m.drawgreatcircle(lon1,lat1,lon2,lat2)
x,y = line.get_data()

line.remove()
del line

line, = plt.plot([],[])

def update(i):
    line.set_data(x[:i], y[:i])

ani = matplotlib.animation.FuncAnimation(fig, update, frames=len(x), interval=100)
ani.save(__file__+".gif", writer="imagemagick", fps=10)
plt.tight_layout()
plt.show()

enter image description here


当我将这段代码复制到Spyder中时,出现了这个错误:“TypeError:'Path'对象不可迭代”。它发生在这一行上,= m.drawgreatcircle(lon1,lat1,lon2,lat2)。如果我在“line”上删除逗号,我会得到一个Path对象,我看到它是一个数组,但我无法索引或访问值。 - Bryan Stafford
根据文档drawgreatcircle返回一个matplotlib.lines.Line2D对象。上面的解决方案利用了这一事实,在我看来,它适用于2013年发布的basemap版本1.0.7,这仍然是最新的官方版本。该问题是在2014年引入的,已经得到修复 ,直到2016年末,因此当前的开发版本也应该返回line2D。 - ImportanceOfBeingErnest
如果您不想升级或降级您的底图安装,那么从路径中获取点应该是可行的。如果 p 是一个路径,则 points = p.vertices 给出了一个二维数组中的点,使得 x = points[:,0]y = points[:,1] 应该给出坐标。不幸的是,我目前无法测试它。 - ImportanceOfBeingErnest
非常感谢。我在尝试升级Basemap(我使用Windows)并尝试获取ImageMagick或FFMpeg时遇到了很大的困难,但最终我成功地在我的计算机上运行了您的代码。非常感谢! - Bryan Stafford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接