#!/usr/bin/env python # coding: utf-8 # A notebook to answer a [StackOverflow question](https://stackoverflow.com/questions/51801109/animate-a-point-between-two-points-along-with-rotating-earth) relating to animating the rotation of a projecton using cartopy # In[ ]: get_ipython().run_line_magic('matplotlib', 'notebook') # In[ ]: import cartopy.crs as ccrs import cartopy.feature as cfeature import matplotlib.animation as animation import matplotlib.image as mimage import matplotlib.pyplot as plt import matplotlib.transforms as mtransforms import numpy as np import shapely.geometry as sgeom plt.figure(figsize=(6, 6)) line = sgeom.LineString([[0, 15], [-140, -40], [120, -20], [0, -20], [-140, 15], [90, 45], [0, 15]]) class HighResPC(ccrs.PlateCarree): @property def threshold(self): return super(HighResPC, self).threshold / 100 projected_line = HighResPC().project_geometry(line, ccrs.Geodetic()) verts = np.concatenate([np.array(l.coords) for l in projected_line]) def setup_axes(ax, x, y): ax.set_global() ax.add_feature(cfeature.LAND) ax.add_feature(cfeature.OCEAN) # Add the projected line to the map. ax.add_geometries( [projected_line], HighResPC(), edgecolor='blue', facecolor='none') # Image from http://madmen.wikia.com/wiki/File:Superman.gif. superman = plt.imread('superman.png') # Scale the actual image down a little. img_size = np.array(superman.shape) / 2 x, y = ax.projection.transform_point(x, y, ccrs.PlateCarree()) # Convert the projected coordinates into pixels. x_pix, y_pix = ax.transData.transform((x, y)) # Make the extent handle the appropriate image size. extent = [x_pix - 0.5 * img_size[1], y_pix - 0.5 * img_size[0], x_pix + 0.5 * img_size[1], y_pix + 0.5 * img_size[0]] bbox = mtransforms.Bbox.from_extents(extent) img = mimage.BboxImage(bbox, zorder=10) img.set_data(superman) ax.add_artist(img) return img def animate_superman(i): i = i % verts.shape[0] ax = plt.gca() ax.remove() ax = plt.axes([0, 0, 1, 1], projection=ccrs.Orthographic( central_latitude=verts[i, 1], central_longitude=verts[i, 0])) ax.coastlines() img = setup_axes(ax, verts[i, 0], verts[i, 1]) # In[ ]: ani = animation.FuncAnimation( plt.gcf(), animate_superman, frames=verts.shape[0], interval=125, repeat=False) ani.save('superman.gif', writer='imagemagick', dpi=plt.gcf().dpi) plt.show()